コード例 #1
0
int main(int argc, char **argv) {
  int raw_mode = 0;
  struct GlobalHeader ghead;

  // parameter check
  if(argc == 1) {
    raw_mode = 0;
  } else if(argc == 2) {
    if(0 != strcmp(argv[1], "-r")) {
      usage();
      return 0;
    }
    raw_mode = 1;
  } else {
    usage();
    return 0;
  }

  // read global header
  if(!raw_mode) {
    // XXX Should check link type and record snapshot length.
    fread(&ghead, sizeof(unsigned char), sizeof(struct GlobalHeader), stdin);
    if(ghead.magic != MAGIC_NUMBER) {
      printf("invalid file format\n");
      return 0;
    }
    printf("PCAP format v%d.%d, ", ghead.majorver, ghead.minorver);
    if(ghead.linklayertype != 1) {
      printf("unsupported link layer type\n");
      return 0;
    }
    printf("link layer type: Ethernet.\n");
  }

  // read each packet
  while (1) {
    int i;
    struct PacketHeader phead;
    struct EthernetHeader ehead;

    printf("\n");

    // packet header
    if (!raw_mode) {
      // XXX Should use length information in decoding below.
      if(sizeof(struct PacketHeader) != fread(&phead, sizeof(unsigned char), sizeof(struct PacketHeader), stdin)) break;
      if(phead.packetsize > ghead.snapshotlength) {
	printf("wrong packet at 0x%08x\n", (int)ftell(stdin));
	return 0;
      }
      printf("<<<PCAP packet\n");
      printf("    packet size: %d\n", phead.packetsize);
      printf("    payload size: %d\n", phead.payloadsize);
    }

    // data captured from wire
    get_ether(&ehead);
    print_ether(&ehead);

    if (ehead.length_type <= 1500) {
      // old style packet
      printf("Old style packet, length = %d\n", ehead.length_type);
      printf("We don't support this packet now\n");
      if (!raw_mode) {
	dump(phead.packetsize-sizeof(ehead), 1);
      }
    } else if (ehead.length_type == 0x0800) {
      // ASSIGNMENT: MODIFY THIS TO PRINT INFORMATION ABOUT ENCAPSULATED PAYLOAD.
      struct IPv4Header ipv4head;
      get_ipv4(&ipv4head);
      print_ipv4(&ipv4head);

      if(ipv4head.protocol == 4) {
	printf("IP packet\n");
	printf("Wedon't support this packet now\n");
	dump(ipv4head.datalen-sizeof(ipv4head), 1);
      } else if(ipv4head.protocol ==  6) {
	struct TCPHeader tcphead;
	get_tcp(&tcphead);
	print_tcp(&tcphead);

	// get payload in TCP packet
	//dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 2);
	if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) {
	  dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 0);
	} else {
	  dump((ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0);
	}
      } else if(ipv4head.protocol == 17) {
	struct UDPHeader udphead;
	get_udp(&udphead);
	assert(udphead.size == ipv4head.datalen-sizeof(ipv4head));
	print_udp(&udphead);

	// get payload in UDP packet
	if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) {
	  dump(udphead.size-sizeof(udphead), 0);
	} else {
	  dump((udphead.size-sizeof(udphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0);
	}
      } else {
	printf("Unexpected IP packet\n");
	dump(ipv4head.datalen-sizeof(ipv4head), 1);
      }

      if(!raw_mode) {
	if(phead.packetsize > sizeof(ehead)+ipv4head.datalen) {
	  printf("pad:\n");
	  dump(phead.packetsize-sizeof(ehead)-ipv4head.datalen, 1);
	}
      }
    } else if(ehead.length_type == 0x0806) {
      printf("ARP packet\n");
      printf("We don't support this packet now\n");
      if (!raw_mode) {
	dump(phead.packetsize-sizeof(ehead), 1);
      }
    } else if(ehead.length_type == 0x86DD) {
      printf("IPv6 packet\n");
      printf("We don't support this packet now\n");
      if (!raw_mode) {
	dump(phead.packetsize-sizeof(ehead), 1);
      }
    } else {
      printf("Unexpected Ethernet packet\n");
      if (!raw_mode) {
	dump(phead.packetsize-sizeof(ehead), 1);
      }
    }
  }
  return 0;
}
コード例 #2
0
ファイル: udp_sync.c プロジェクト: azuwis/mplayer
// gets a datagram from the master with or without blocking.  updates
// master_position if successful.  if the master has exited, returns 1.
// returns -1 on error.
// otherwise, returns 0.
static int get_udp(int blocking, float *master_position)
{
    char mesg[100];

    int chars_received = -1;
    int n;

    static int sockfd = -1;
    if (sockfd == -1) {
        struct timeval tv = { .tv_sec = 30 };
        struct sockaddr_in servaddr = { 0 };

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1)
            return -1;

        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(udp_port);
        bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    }

    set_blocking(sockfd, blocking);

    while (-1 != (n = recvfrom(sockfd, mesg, sizeof(mesg)-1, 0,
                               NULL, NULL))) {
        // flush out any further messages so we don't get behind
        if (chars_received == -1)
            set_blocking(sockfd, 0);

        chars_received = n;
        mesg[chars_received] = 0;
        if (strcmp(mesg, "bye") == 0)
            return 1;
        sscanf(mesg, "%f", master_position);
    }

    return 0;
}

void send_udp(const char *send_to_ip, int port, char *mesg)
{
    static int sockfd = -1;
    static struct sockaddr_in socketinfo;

    if (sockfd == -1) {
        static const int one = 1;
        int ip_valid = 0;

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1)
            exit_player(EXIT_ERROR);

        // Enable broadcast
        setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));

#if HAVE_WINSOCK2_H
        socketinfo.sin_addr.s_addr = inet_addr(send_to_ip);
        ip_valid = socketinfo.sin_addr.s_addr != INADDR_NONE;
#else
        ip_valid = inet_aton(send_to_ip, &socketinfo.sin_addr);
#endif

        if (!ip_valid) {
            mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_InvalidIP);
            exit_player(EXIT_ERROR);
        }

        socketinfo.sin_family = AF_INET;
        socketinfo.sin_port   = htons(port);
    }

    sendto(sockfd, mesg, strlen(mesg), 0, (struct sockaddr *) &socketinfo,
           sizeof(socketinfo));
}

// this function makes sure we stay as close as possible to the master's
// position.  returns 1 if the master tells us to exit, 0 otherwise.
int udp_slave_sync(MPContext *mpctx)
{
    // grab any waiting datagrams without blocking
    int master_exited = get_udp(0, &udp_master_position);

    while (!master_exited) {
        float my_position = mpctx->sh_video->pts;

        // if we're way off, seek to catch up
        if (FFABS(my_position - udp_master_position) > udp_seek_threshold) {
            abs_seek_pos  = SEEK_ABSOLUTE;
            rel_seek_secs = udp_master_position;
            break;
        }

        // normally we expect that the master will have just played the
        // frame we're ready to play.  break out and play it, and we'll be
        // right in sync.
        // or, the master might be up to a few seconds ahead of us, in
        // which case we also want to play the current frame immediately,
        // without waiting.
        // UDP_TIMING_TOLERANCE is a small value that lets us consider
        // the master equal to us even if it's very slightly ahead.
        if (udp_master_position + UDP_TIMING_TOLERANCE > my_position)
            break;

        // the remaining case is that we're slightly ahead of the master.
        // usually, it just means we called get_udp() before the datagram
        // arrived.  call get_udp again, but this time block until we receive
        // a datagram.
        master_exited = get_udp(1, &udp_master_position);
    }

    return master_exited;
}