about summary refs log tree commit diff stats
path: root/data/maps/daedalus/rooms/Coin Tower.txtpb
blob: 177fc6e0679084d86a24a6db59bc4489d20d300c (plain) (blame)
1
2
3
4
5
6
7
8
9
name: "Coin Tower"
panel_display_name: "Northeast Area"
panels {
  name: "RAIN"
  path: "Panels/Entry/db_2"
  clue: "rain"
  answer: "snow"
  symbols: CROSS
}
/* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "retransmit.h"

#include <libwifi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "transmit.h"

static pthread_mutex_t retransmitter_mutex = PTHREAD_MUTEX_INITIALIZER;

void ack_map_init(struct ack_map *map)
{
  map->top = NULL;
}

void ack_map_add(struct ack_map *map, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size)
{
  struct ack_map_node *cur = map->top;
  struct ack_map_node *prev = NULL;

  while (cur != NULL)
  {
    prev = cur;
    cur = cur->next;
  }

  struct ack_map_node *next = (struct ack_map_node *)malloc(sizeof(struct ack_map_node));
  next->next = NULL;
  memcpy(next->dst_addr, dst_addr, 6);
  next->packet = (unsigned char *)malloc(packet_size);
  memcpy(next->packet, packet, packet_size);
  next->packet_size = packet_size;
  next->retries_left = 7;

  if (prev == NULL)
  {
    map->top = next;
  }
  else
  {
    prev->next = next;
  }
}

void ack_map_pop(struct ack_map *map)
{
  if (map->top != NULL)
  {
    struct ack_map_node *cur = map->top;
    map->top = cur->next;

    free(cur->packet);
    free(cur);
  }
}

int ack_map_length(struct ack_map *map)
{
  int result = 0;

  struct ack_map_node *cur = map->top;
  while (cur != NULL)
  {
    result++;

    cur = cur->next;
  }

  return result;
}

void ack_map_clear(struct ack_map *map)
{
  while (map->top != NULL)
  {
    ack_map_pop(map);
  }
}

void *retransmit_thread(void *arg)
{
  struct retransmitter *retransmitter = (struct retransmitter *)arg;

  for (;;)
  {
    pthread_mutex_lock(&retransmitter_mutex);

    if (retransmitter->quit)
    {
      pthread_mutex_unlock(&retransmitter_mutex);

      break;
    }

    struct ack_map_node *cur = retransmitter->messages.top;
    if (cur != NULL)
    {
      send_packet_with_radiotap(retransmitter->sock, retransmitter->device_index, cur->dst_addr, cur->packet, cur->packet_size);

      // Set retransmit flag for future.
      cur->packet[1] |= (1 << 3);

      cur->retries_left--;

      if (cur->retries_left <= 0)
      {
        ack_map_pop(&retransmitter->messages);
      }
    }

    pthread_mutex_unlock(&retransmitter_mutex);

    usleep(5000);
  }

  return NULL;
}

struct retransmitter *start_retransmit_thread(int sock, int device_index)
{
  struct retransmitter *retransmitter = (struct retransmitter *)malloc(sizeof(struct retransmitter));
  retransmitter->sock = sock;
  retransmitter->device_index = device_index;
  ack_map_init(&retransmitter->messages);
  retransmitter->quit = false;

  pthread_create(&retransmitter->thread_id, NULL, &retransmit_thread, retransmitter);

  return retransmitter;
}

void send_until_acked(struct retransmitter *retransmitter, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size)
{
  pthread_mutex_lock(&retransmitter_mutex);

  ack_map_add(&retransmitter->messages, dst_addr, packet, packet_size);

  printf("Adding message for " MACSTR ". Current length: %d\n", MAC2STR(dst_addr), ack_map_length(&retransmitter->messages));

  pthread_mutex_unlock(&retransmitter_mutex);
}

void handle_ack(struct retransmitter *retransmitter)
{
  pthread_mutex_lock(&retransmitter_mutex);

  if (retransmitter->messages.top != NULL)
  {
    retransmitter->messages.top->retries_left = 0;
  }

  printf("Received ACK. Current length: %d\n", ack_map_length(&retransmitter->messages));

  pthread_mutex_unlock(&retransmitter_mutex);
}

void free_retransmitter(struct retransmitter *retransmitter)
{
  pthread_mutex_lock(&retransmitter_mutex);
  retransmitter->quit = true;
  pthread_mutex_unlock(&retransmitter_mutex);

  pthread_join(retransmitter->thread_id, NULL);

  ack_map_clear(&retransmitter->messages);
  free(retransmitter);
}