Example #1
0
/* If an entry already exists for an href, then return the entry.
   Else, return NULL. */
static entry *fetch_entry (char *href)
{
  int hash = hash_url (href);
  entry *l;

  if (hash_table[hash].count)
    for (l = hash_table[hash].head; l != NULL; l = l->next)
      {
        if (!strcmp (l->href, href))
          return l;
      }
  
  return NULL;
}
Example #2
0
/* We're making a new annotation to a url.  Pass in the title,
   author, and text of the annotation. */
mo_status mo_new_pan (char *url, char *title, char *author, char *text)
{
  entry *l = fetch_entry (url);
  int id = ++max_pan_id;

  if (!title || !*title)
    title = strdup ("Annotation with no title");
  if (!author || !*author)
    author = strdup ("No author name");
  
  /* Create a new entry if we have to. */
  if (!l)
    l = new_entry (hash_url (url), url);

  /* Register the new annotation id with the entry. */
  add_an_to_entry (l, id);

  mo_write_pan (id, title, author, text);

  return mo_succeed;
}
Example #3
0
static void mo_read_pan_file (char *filename)
{
  FILE *fp;
  char line[MO_LINE_LENGTH];
  char *status;
  entry *l;
  
  fp = fopen (filename, "r");
  if (!fp)
    goto screwed_no_file;
  
  status = fgets (line, MO_LINE_LENGTH, fp);
  if (!status || !(*line))
    goto screwed_with_file;
  
  /* See if it's our format. */
  if (strncmp (line, NCSA_PAN_LOG_FORMAT_COOKIE_ONE,
               strlen (NCSA_PAN_LOG_FORMAT_COOKIE_ONE)))
    goto screwed_with_file;
  
  /* Go fetch the name on the next line. */
  status = fgets (line, MO_LINE_LENGTH, fp);
  if (!status || !(*line))
    goto screwed_with_file;
  
  /* Start grabbing documents and lists of annotations. */
  while (1)
    {
      char *url;
      char *p;
      
      status = fgets (line, MO_LINE_LENGTH, fp);
      if (!status || !(*line))
        goto done;
      
      url = strtok (line, " ");
      if (!url)
        goto screwed_with_file;
      url = strdup (url);
      /* We don't use the last-accessed date... yet. */
      /* lastdate = strtok (NULL, "\n"); blah blah blah... */

      l = new_entry (hash_url (url), url);

      free (url);

      while (p = strtok (NULL, " "))
        {
          int a = atoi (p);
          if (a)
            {
              add_an_to_entry (l, a);
              if (a > max_pan_id)
                max_pan_id = a;
            }
        }
    }      

 done:
  fclose (fp);
  return;

 screwed_with_file:
  fclose (fp);
  return;

 screwed_no_file:
  return;
}
Example #4
0
static void test_UrlHash(void)
{
  hash_url(TEST_URL_1);
  hash_url(TEST_URL_2);
  hash_url(TEST_URL_3);
}
Example #5
0
int main(int argc, char *argv[]) {
    if (argc < 3) { // Checking for correct arquments
        printf("Useage: dhtnode own_hostname own_port\n");
        exit(0);
    }
    char* my_url = argv[1];
    char* my_port = argv[2];
    
    sha1_t my_hash; // Create hash for own address
    hash_url(my_url, my_port, my_hash);
    fd_set master;
    fd_set rfds;
    int retval;
    int running = 1;
    int listensock = create_listen_socket(my_port);
    con_t server;
    memset(&server,0,sizeof server);
    con_t left;
    memset(&left,0,sizeof left);
    con_t right;
    memset(&right,0,sizeof right);
    FD_SET(STDIN_FILENO, &master);
    FD_SET(listensock, &master);
    
    int fdmax = listensock;
    struct timeval looptime;

    while (running) {
        looptime.tv_sec = 1;
        looptime.tv_usec = 0;
        rfds = master;
        retval = select(fdmax + 1, &rfds, NULL, NULL, &looptime);

        if (retval == -1)
            die("select failed");
        else if (retval) {
            if (FD_ISSET(STDIN_FILENO, &rfds)) {
                int argcount;
                char** arguments = NULL;
                int cmd = getcommand(STDIN_FILENO, &argcount, &arguments);
                printf("got command\n");
                if (cmd < 0) {
                    //TODO handle different errors differently
                    printf("error: %d\n", cmd);
                    exit(-1);
                }
                switch (cmd) {
                    case USER_EXIT:
                        if(server.state != ST_EMPTY && (argcount == 0 || strcmp(arguments[0],"force"))){//remember strcmp returns 0 on match
                            printf("trying to exit\n");
                            send_dht_pckt(server.socket,DHT_DEREGISTER_BEGIN,my_hash,my_hash,0,NULL);
                        }
                        else{
                            printf("exiting\n");
                            running = 0;
                        }
                        freeargs(argcount, arguments);
                        break;
                    case USER_CONNECT:
                        if(argcount != 2){
                            printf("usage: connect url port\n");
                            freeargs(argcount,arguments);
                            break;
                        }
                        if(server.state != ST_EMPTY){
                            printf("Already connected to the server. Use exit to disconnect.\n");
                            freeargs(argcount,arguments);
                            break;
                        }
                        printf("connecting to %s:%s\n", arguments[0], arguments[1]);
                        int sock = create_connection(arguments[0], arguments[1]);
                        printf("connection made\n");
                        FD_SET(sock, &master);
                        if(sock > fdmax) fdmax = sock;
                        server.socket = sock;
                        server.state = ST_WF_SER_SHAKE;
                        
                        freeargs(argcount, arguments);
                        break;
                    case USER_PRINT:
                        printf("printing...\n");
                        for(int i = 0; i < argcount; i++){
                            printf("%s:\n",arguments[i]);
                            if(!strcmp(arguments[i],"sockets")){
                               printf("server, %d %s\n",server.socket,(server.socket != 0 && FD_ISSET(server.socket,&master))? "is set":"not set"); 
                               printf("right, %d %s\n",right.socket,(right.socket != 0 && FD_ISSET(right.socket,&master))? "is set":"not set"); 
                               printf("left, %d %s\n",left.socket,(left.socket != 0 && FD_ISSET(left.socket,&master))? "is set":"not set"); 
                            }
                            else if(!strcmp(arguments[i],"states")){
                                printf("server, %d\n",server.state);
                                printf("right, %d\n",right.state);
                                printf("left, %d\n",left.state);
                            }
                        }
                        freeargs(argcount,arguments);
                        break;
                    case USER_UNKNW_CMD:
                        printf("unknown command, line was:");
                        for (int i = 0; i < argcount; i++) {
                            printf(" %s", arguments[i]);
                        }
                        printf("\n");
                        freeargs(argcount, arguments);
                        break;
                }
            }
            //check for new connections
            if (FD_ISSET(listensock, &rfds)) {
                printf("someone is connecting\n");
                if(right.state == ST_EMPTY){
                    right.socket = accept_connection(listensock);
                    if(right.socket < 0){
                        die(strerror(errno));
                    }
                    FD_SET(right.socket, &master);
                    if(right.socket > fdmax) fdmax = right.socket;
                    right.state = ST_WF_CLI_SHAKE;
                } else if (left.state == ST_EMPTY) {
                    left.socket = accept_connection(listensock);
                    if(left.socket < 0){
                        die(strerror(errno));
                    }
                    FD_SET(left.socket, &master);
                    if(left.socket > fdmax) fdmax = left.socket;
                    left.state = ST_WF_CLI_SHAKE;
                }
            }
            //check for msg from server
            if(server.state != ST_EMPTY && FD_ISSET(server.socket, &rfds)){
                int status;
                if(server.state == ST_WF_SER_SHAKE){
                    printf("getting shake\n");
                    status = recvdata(server.socket, NULL);
                    if(status == NTW_SERVER_SHAKE){
                        printf("shaking back\n");
                        send_shake(server.socket, NTW_CLIENT_SHAKE);
                        unsigned char formated_url[strlen(my_url)+3];
                        format_url(my_url, my_port, formated_url);
                        printf("sending DHT_REGISTER_BEGIN\n");
                        send_dht_pckt(server.socket,DHT_REGISTER_BEGIN,my_hash,my_hash,strlen(my_url)+3,formated_url);
                        server.state = ST_ONLINE;
                    }
                    //TODO error handling
                    /*On correct shake shake back and send DHT_REGISTER_BEGIN
                     with our sha1 as sender and target and
                     our port+url as payload
                     switch state to ST_ONLINE*/
                } else{
                    DHT_t packet;
                    memset(&packet, 0, sizeof packet);
                    status = recvdata(server.socket, &packet);
                    if(status != NTW_PACKET_OK){
                        switch(status){
                            case NTW_ERR_SERIOUS:
                                die(strerror(errno));
                                break;
                            case NTW_DISCONNECT:
                                die("server disconnected");
                                break;
                            default:
                                printf("getting packet failed somehow\n");
                                memset(&packet, 0, sizeof packet);
                                break;
                        }
                    }
                    printf("received from server:\n");
                    print_dht_packet(&packet);
                    //TODO error handling
                    uint16_t reqt = ntohs(packet.req_type);
                    if(server.state == ST_ONLINE && reqt == DHT_REGISTER_FAKE_ACK){
                        printf("fake ack received\n");
                        /*send DHT_REGISTER_DONE to server
                         target and sender are both our hash
                         state to ST_IDLING*/
                        int a = send_dht_pckt(server.socket, DHT_REGISTER_DONE, my_hash, my_hash, 0, NULL);
                        if(a == 0) server.state = ST_IDLING;
                        else exit(1); // or error handling
                        
                    } else if(server.state == ST_IDLING && reqt == DHT_REGISTER_BEGIN){
                        printf("dht_register_begin received\n");
                        /*open connection to the new node
                         which port+url is in packet and
                         send data + DHT_REGISTER_ACK
                         our hash sender and target
                         state to ST_WF_REG_DONE*/
                        char his_url[packet.pl_length-2];
                        strcpy(his_url,(char*)packet.payload+2);
                        uint16_t* port = (uint16_t*)packet.payload;
                        *port = ntohs(*port);
                        char his_port[10];
                        sprintf(his_port,"%u",*port);
                        int sock = create_connection(his_url,his_port);
                        FD_SET(sock, &master);
                        if(sock > fdmax) fdmax = sock;
                        con_t* pal;
                        pal = (right.state == ST_EMPTY) ? &right : &left;
                        memcpy(pal->hash,packet.sender,20);
                        pal->socket = sock;
                        pal->state = ST_WF_SER_SHAKE;
                        //server.state = ST_WF_REG_DONE;
                        
                    } else if(server.state == ST_IDLING && reqt == DHT_REGISTER_DONE){
                        printf("received reg done\n");
                        //server.state = ST_IDLING;
                        /*dump old data and return to ST_IDLING*/
                    } else if(server.state == ST_IDLING && reqt == DHT_DEREGISTER_ACK){
                        printf("dereg ack received\n");
                        /*open connection to neighbours their urls are as
                         payload of the package and send data and
                         DHT_DEREGISTER_BEGIN (our hash as sender and target)
                         change to ST_WF_DEREG_DONE*/
                        uint16_t port_buf = ((uint16_t*)packet.payload)[0];
                        port_buf = ntohs(port_buf);
                        char port1[10];
                        sprintf(port1,"%u",port_buf);
                        char url1[30];
                        strcpy(url1,(char*)(packet.payload+2));
                        
                        port_buf = ((uint16_t*)(packet.payload+3+strlen(url1)))[0];
                        port_buf = ntohs(port_buf);
                        char port2[10];
                        sprintf(port2,"%u",port_buf);
                        char url2[30];
                        strcpy(url2,(char*)(packet.payload+5+strlen(url1)));
                        printf("parsing got:\nurl1 = %s:%s\nurl2 = %s:%s\n", url1, port1, url2, port2);
                        
                        //connect to right neighbour
                        right.socket = create_connection(url1,port1);
                        FD_SET(right.socket, &master);
                        if(right.socket > fdmax) fdmax = right.socket;
                        hash_url(url1,port1,right.hash);
                        right.state = ST_WF_SER_SHAKE;
                        //connect to left neighbour
                        left.socket = create_connection(url2,port2);
                        FD_SET(left.socket, &master);
                        if(left.socket > fdmax) fdmax = left.socket;
                        hash_url(url2,port2,left.hash);
                        left.state = ST_WF_SER_SHAKE;
                        
                        server.state = ST_WF_DEREG_DONE;
                    } else if(server.state == ST_IDLING && reqt == DHT_DEREGISTER_DENY){
                        printf("dereg deny received\n");
                        /*tell user that leaving is impossible
                         return to ST_IDLING*/
                        printf("Unable to exit. You are the last node. To over-ride this use exit force command.\n");
                        server.state = ST_IDLING;
                    } else if(server.state == ST_WF_DEREG_DONE && reqt == DHT_DEREGISTER_DONE){
                        if(right.state == ST_DEREG_DATA_SENT && !memcmp(right.hash, packet.sender, 20)){
                            FD_CLR(right.socket, &master);
                            close(right.socket);
                            memset(&right,0,sizeof right);
                        }
                        else if(left.state == ST_DEREG_DATA_SENT && !memcmp(left.hash, packet.sender, 20)){
                            FD_CLR(left.socket, &master);
                            close(left.socket);
                            memset(&left,0,sizeof left);
                        }
                        if(left.state == ST_EMPTY && right.state == ST_EMPTY){
                            printf("leaving the network\n");
                            close(server.socket);
                            FD_CLR(server.socket, &master);
                            memset(&server,0,sizeof server);
                            printf("left the network\n");
                        }
                        /*close the connection to server
                         state to ST_EMPTY*/
                        }
                    }
                }
            }
            for(int i = 0; i<2;i++){
                con_t* neighbour = (i == 0) ? &right : &left;
            //check for msg from right and left neighbour
            if(neighbour->state != ST_EMPTY && FD_ISSET(neighbour->socket, &rfds)){
                int status;
                if(neighbour->state == ST_WF_CLI_SHAKE){
                    /* prepare to receive data
                     switch state to ST_RCV_DATA_REG or
                     ST_RCV_DATA_DEREG depending on server state*/
                    status = recvdata(neighbour->socket, NULL);
                    if(status == NTW_CLIENT_SHAKE){
                        if(server.state == ST_ONLINE){
                            neighbour->state = ST_RCV_DATA_REG;
                        }
                        if(server.state == ST_IDLING){ 
                            neighbour->state = ST_RCV_DATA_DEREG;
                        }
                    } else {
                        switch(status){
                            case NTW_ERR_SERIOUS:
                                die(strerror(errno));
                                break;
                            case NTW_DISCONNECT:
                                printf("%s disconnected\n",(i)?"left":"right");
                                FD_CLR(neighbour->socket,&master);
                                memset(neighbour,0,sizeof *neighbour);
                                break;
                            default:
                                printf("getting shake failed somehow\n");
                                break;
                        }
                    }
                } else if (neighbour->state == ST_WF_SER_SHAKE){
                    /* answer with client shake and pump your data to the neighbour
                     after that send DHT_REGISTER_ACK or DHT_DEREG_BEGIN
                     either way after this the connection to neighbour can be disconnected*/
                    status = recvdata(neighbour->socket, NULL);
                    if(status == NTW_SERVER_SHAKE){
                        printf("shaking back\n");
                        send_shake(neighbour->socket, NTW_CLIENT_SHAKE);
                        if(server.state == ST_IDLING){ //we should end with DHT_REGISTER_ACK
                            send_dht_pckt(neighbour->socket,DHT_REGISTER_ACK,my_hash,my_hash,0,NULL);
                            FD_CLR(neighbour->socket, &master);
                            close(neighbour->socket);
                            memset(neighbour,0,sizeof *neighbour);
                        }
                        if(server.state == ST_WF_DEREG_DONE){ //we should end with DHT_DEREGISTER_BEGIN
                            send_dht_pckt(neighbour->socket,DHT_DEREGISTER_BEGIN,my_hash,my_hash,0,NULL);
                            FD_CLR(neighbour->socket, &master);
                            close(neighbour->socket);
                            neighbour->state = ST_DEREG_DATA_SENT;
                        }
                    } else {
                        switch(status){
                            case NTW_ERR_SERIOUS:
                                die(strerror(errno));
                                break;
                            case NTW_DISCONNECT:
                                die("neighbour disconnected");
                                break;
                            default:
                                printf("getting shake failed somehow\n");
                                break;
                        }
                    }
                    
                } else{
                    DHT_t packet;
                    memset(&packet, 0, sizeof packet);
                    status = recvdata(neighbour->socket, &packet);
                    printf("received package from %s:\n",(i)?"left":"right");
                    print_dht_packet(&packet);
                    if(status != NTW_PACKET_OK){
                        switch(status){
                            case NTW_ERR_SERIOUS:
                                die(strerror(errno));
                                break;
                            case NTW_DISCONNECT:
                                printf("%s neighbour disconnected.\n",(i)?"left":"right");
                                FD_CLR(neighbour->socket,&master);
                                close(neighbour->socket);
                                memset(neighbour,0,sizeof * neighbour);
                                break;
                            case NTW_ERR_TIMEOUT:
                                printf("package from %s timed out!\n",(i)?"left":"right");
                                memset(&packet,0,sizeof packet);
                                break;
                        }
                    }
                    uint16_t reqt = ntohs(packet.req_type);
                    if(neighbour->state == ST_RCV_DATA_REG && reqt == DHT_REGISTER_ACK){
                        /*all data is now received */
                        FD_CLR(neighbour->socket, &master);
                        close(neighbour->socket);
                        memset(neighbour,0,sizeof *neighbour);
                        neighbour->state = ST_REG_DATA_RCVD;
                        if(right.state == ST_REG_DATA_RCVD && left.state == ST_REG_DATA_RCVD){
                            send_dht_pckt(server.socket, DHT_REGISTER_DONE, my_hash, my_hash, 0, NULL);
                            right.state = ST_EMPTY;
                            left.state = ST_EMPTY;
                            server.state = ST_IDLING;
                        }
                    } else if(neighbour->state == ST_RCV_DATA_DEREG && reqt == DHT_DEREGISTER_BEGIN){
                        send_dht_pckt(server.socket, DHT_DEREGISTER_DONE, packet.sender, my_hash, 0, NULL);
                        FD_CLR(neighbour->socket, &master);
                        close(neighbour->socket);
                        memset(neighbour,0,sizeof *neighbour);
                    }
                }
            }
        }
    }

    close(listensock);

    return 0;
}