Пример #1
0
static int dispatch_msg(int efd, struct epoll_event *ep_event, msg_handler_fn_t msg_handler)
{
	char buf[MAX_BUF_LEN];
	struct msg_request_head *head;
	int fd = ep_event->data.fd;
	uint32_t event = ep_event->events;

	/* An error has occured on this fd, or the socket is not
	   ready for reading (why were we notified then?) */
	if ((event& EPOLLERR) || (event & EPOLLHUP) || (!(event & EPOLLIN)))
	{
		DEBUG_ERROR("error epoll event: %d, err = %d, hup = %d, in = %d\n", 
			   event, EPOLLERR, EPOLLHUP, EPOLLIN);

		epoll_ctl(efd, EPOLL_CTL_ADD, fd, NULL);
		close(fd);

		return -1;
	}

	if (0 != recv_safe(fd, buf, sizeof(buf))) 
	{
		response_errno(fd, -1);

		return -1;
	}

	head = (struct msg_request_head *) buf;
	msg_convert_request_head(head);

	msg_handler(fd, head->type, head->operation, buf + sizeof(*head));

	return 0;
}
/**
 * GET function
 * Performs the receiving half of a request
 */
void get(SOCKET s, SOCKADDR_IN sa, char * username, char* filename, int client_num, int server_num, FILE* logfile){
    char buffer[FRAME_SIZE];
    int count, offset, recv, filesize, size;
    char tracebuf[128];

    FILE* recv_file = fopen(filename, "wb");

    if(recv_safe(s, sa, buffer, FRAME_SIZE, 101) == 101){ // Receives the filesize negotiation packet

        memcpy(&filesize, buffer + (3 * sizeof(char)), sizeof(int));

        cout << "Got filesize " << filesize << " starting transfer..." << endl;

        sprintf(tracebuf, "Filesize %d", filesize);
        write_log(logfile, username, tracebuf);

        offset = recv = count = 0;

        int expected_size = WINDOW_SIZE + 1;
        int recv_count, nak;
        int next = 0;
        int packet_id;
        // Receive the file
        while(1){
            nak = -1;
            recv_count = 0;
            next = offset;
            while(count < filesize && recv_count < WINDOW_SIZE){
                if(filesize - count >= (FRAME_SIZE))    size = (FRAME_SIZE / sizeof(char));         // Read the full buffer
                else                                    size = ((filesize - count) / sizeof(char)); // Read a subset of the buffer
                if((packet_id = recv_packet(s,sa,buffer,FRAME_SIZE,offset)) == offset){ // Receive the packet from the peer
                    count += FRAME_SIZE;
                    fwrite(buffer,sizeof(char),size,recv_file);     // Write to the output file
                    
                    sprintf(tracebuf, "Recv %d (%d of %d)", offset, count, filesize);
                    write_log(logfile, username, tracebuf);

                    offset = (offset + 1) % expected_size;    
                    recv_count++;
                }else if(packet_id < 0){
                    nak = offset;
                    break;
                }else if(packet_id == 101){
                    fclose(recv_file);
                    return get(s, sa, username, filename, client_num, server_num, logfile);
                }
            }
            while(recv_count > 0 || nak >= 0){
                memset(buffer,0,FRAME_SIZE);
                if(next != nak) strncpy(buffer, "ACK", 3);  // Send ACK
                else            strncpy(buffer, "NAK", 3);  // Send NAK
                send_packet(s,sa,buffer,FRAME_SIZE,next); // Send acknowledgement
                recv_count--;
                if(next == nak){
                    offset = nak;
                    sprintf(tracebuf, "Sent NAK for %d", nak);
                    write_log(logfile, username, tracebuf);
                    break; 
                } // As soon as we send a NAK we can break
                next = (next + 1) % expected_size;
            }

            if(count >= filesize) break;
        }
        strncpy(buffer, "ALL", 3);
        send_packet(s, sa, buffer, FRAME_SIZE, next);
        cout << "Transfer completed! " << count << " bytes received" << endl;
        fclose(recv_file);
    }else{
        fclose(recv_file);
        return get(s, sa, username, filename, client_num, server_num, logfile);
    }
}
Пример #3
0
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
{
  struct sockaddr_storage addr;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
  struct iovec iov = { buf, sizeof (buf) };
  StunMessage request;
  StunMessage response;
  StunValidationStatus validation;
  StunAgent *agent = NULL;

  struct msghdr mh =
  {
    .msg_name = (struct sockaddr *)&addr,
    .msg_namelen = sizeof (addr),
    .msg_iov = &iov,
    .msg_iovlen = 1,
    .msg_control = ctlbuf,
    .msg_controllen = sizeof (ctlbuf)
  };

  size_t len = recv_safe (sock, &mh);
  if (len == (size_t)-1)
    return -1;

  validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);

  if (validation == STUN_VALIDATION_SUCCESS) {
    agent = newagent;
  }
  else {
    validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
    agent = oldagent;
  }

  /* Unknown attributes */
  if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
  {
    stun_agent_build_unknown_attributes_error (agent, &response, buf,
        sizeof (buf), &request);
    goto send_buf;
  }

  /* Mal-formatted packets */
  if (validation != STUN_VALIDATION_SUCCESS ||
      stun_message_get_class (&request) != STUN_REQUEST) {
    return -1;
  }

  switch (stun_message_get_method (&request))
  {
    case STUN_BINDING:
      stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
      if (stun_message_has_cookie (&request))
        stun_message_append_xor_addr (&response,
                              STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
                              mh.msg_name, mh.msg_namelen);
      else
         stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
                          mh.msg_name, mh.msg_namelen);
      break;

    default:
      stun_agent_init_error (agent, &response, buf, sizeof (buf),
          &request, STUN_ERROR_BAD_REQUEST);
  }

  iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0);
send_buf:

  len = send_safe (sock, &mh);
  return (len < iov.iov_len) ? -1 : 0;
}


static int run (int family, int protocol, unsigned port)
{
  StunAgent oldagent;
  StunAgent newagent;
  int sock = listen_socket (family, SOCK_DGRAM, protocol, port);
  if (sock == -1)
    return -1;

  stun_agent_init (&oldagent, known_attributes,
      STUN_COMPATIBILITY_RFC3489, 0);
  stun_agent_init (&newagent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);

  for (;;)
    dgram_process (sock, &oldagent, &newagent);
}