コード例 #1
0
ファイル: test_rtp_server.c プロジェクト: BluePandaLi/mpeg4ip
int main (int argc, char *argv[])
{
  struct rtp *session;
  int   rx_port, tx_port, fd;
  uint32_t   read_size, packet_size, number_of_packet;
  uint8_t  buff[BUFFSIZE];
  off_t cur_pos;
  char *ip_addr;
  char filename[1024];
  int c;                        
  struct hostent *h;
  struct utsname myname;
#ifdef HAVE_SRTP
#else
  void *srtp_data;
#endif
  unsigned int extra_len;
  int do_auth = 1, do_encrypt = 1;
  ssize_t readit;
  ssize_t sendit;
  int do_rtcp = false;

  // Setting of default session 
  if(uname(&myname) < 0){
    fprintf(stderr,"uname\n");
    exit(1);
  }
  if((h = gethostbyname(myname.nodename)) == NULL) {
    herror("gethostbyname");
    exit(1);
  }
  ip_addr = strdup(inet_ntoa(*((struct in_addr *)h->h_addr)));
  rx_port = 15002;
  tx_port = 15000;

  // Option
  opterr = 0;
  while((c = getopt(argc, argv, "acdehi:r:t:f:")) != -1){
    switch (c) {
    case 'a':
      do_auth = 0;
      break;
    case 'c':
      do_rtcp = 1;
 	break;
    case 'd':
      dump_pak = true;
 	break;
    case 'e':
      do_encrypt = 0;
      break;
    case 'h':
      printf("Usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n");
      printf("Default values are as follows...\n");
      printf("ip_addr = %s\n", ip_addr);
      printf("rx_port = %d\n", rx_port);
      printf("tx_port = %d\n", tx_port);
      printf("Filename = %s\n", filename);
      exit(-1);
    case 'i':
      strcpy(ip_addr, optarg);
      break;
    case 'r':
      rx_port = atoi(optarg);
      break;
    case 't':
      tx_port = atoi(optarg);
      break;
    case 'f':
      strcpy(filename,optarg);
      break;
    case '?':
      printf("usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n");
      exit(1);
    }
  }
  if (optind < argc) {
    for(; optind < argc; optind++) {
      printf("error->%s(#%d): put -[i|r|t|f] \n", argv[optind],optind-1);
    }
    exit(1);
  }

  // display session information
  printf("\n-Session Information-\n");
  printf("  ip_addr = %s\n", ip_addr);
  printf("  rx_port = %d\n", rx_port);
  printf("  tx_port = %d\n", tx_port);
  printf("  filename = %s\n", filename);
  printf("Press Return key...");
  //  getchar();

  // Open Original File to compare with received file
  if((fd = open(filename, O_RDONLY)) == -1){
    perror(filename);
    exit(1);
  }
  rtp_stream_params_t rsp;
  rtp_default_params(&rsp);
  rsp.rtp_addr = ip_addr;
  rsp.rtp_rx_port = rx_port;
  rsp.rtp_tx_port = tx_port;
  rsp.rtp_ttl = TTL;
  rsp.rtcp_bandwidth = RTCP_BW;
  rsp.rtp_callback = c_rtp_callback;
  rsp.transmit_initial_rtcp = 1;
  if ( (session = rtp_init_stream(&rsp) ) == NULL){
    exit(-1);
  }
  rtp_set_my_ssrc(session,OUR_SSRC);

#ifdef HAVE_SRTP
	/////////// start will
	//set NULL security services
  //uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
  srtp_policy_t policy;
  char key[64];
  char keystr[128];
  uint ix;
#if 1
  strcpy(keystr, "c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451");
  hex_string_to_octet_string(key, keystr, 60);
#else
  memset(key, 0, sizeof(key));
#endif

  for (ix = 0; ix < 30; ix++) {
    printf("%02x ", key[ix]);
  }
  printf("\n");
#if 0
  // NULL cipher
  policy.key                 =  (uint8_t *) key;
  policy.ssrc.type           = ssrc_any_outbound; //ssrc_specific;
  policy.ssrc.value          = 0x96;//OUR_SSRC;
  policy.rtp.cipher_type     = NULL_CIPHER;
  policy.rtp.cipher_key_len  = 0; 
  policy.rtp.auth_type       = NULL_AUTH;
  policy.rtp.auth_key_len    = 0;
  policy.rtp.auth_tag_len    = 0;
  policy.rtp.sec_serv        = sec_serv_none;
  policy.rtcp.cipher_type    = NULL_CIPHER;
  policy.rtcp.cipher_key_len = 0; 
  policy.rtcp.auth_type      = NULL_AUTH;
  policy.rtcp.auth_key_len   = 0;
  policy.rtcp.auth_tag_len   = 0;
  policy.rtcp.sec_serv       = sec_serv_none;   
  policy.next                = NULL;
#else
  //confidentiality only, no auth
  crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
  crypto_policy_set_rtcp_default(&policy.rtcp);
  policy.ssrc.type  = ssrc_any_outbound;
  policy.key  = (uint8_t *) key;
  policy.next = NULL;
  policy.rtp.sec_serv = sec_serv_conf;//sec_servs;
  policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
#endif
  err_status_t status;

  printf("ABOUT TO SRTP_INIT\n");
  status = srtp_init();
  if (status) {
    printf("error: srtp initialization failed with error code %d\n", status);
    exit(1);
  }
  printf("ABOUT TO SRTP_CREAT\n");
  srtp_ctx_t *srtp_ctx = NULL;
  status = srtp_create(&srtp_ctx, &policy);
  if (status) {
    printf("error: srtp_create() failed with code %d\n", status);
    exit(1);
  }
  printf("DONE WITH SRTP_CREATE\n");
  extra_len = 0;
#else

  extra_len = 0;
  srtp_data = NULL;
#endif
  rtp_encryption_params_t params;
  params.rtp_encrypt = ENCRYPT_FUNCTION;
  params.rtcp_encrypt = RTCP_ENCRYPT_FUNCTION;
  params.rtp_decrypt = DECRYPT_FUNCTION;
  params.rtcp_decrypt = RTCP_DECRYPT_FUNCTION;
  params.userdata = srtp_data;
  params.rtp_auth_alloc_extra = params.rtcp_auth_alloc_extra = 0;

  rtp_set_encryption_params(session, &params);

  if (do_rtcp) {
    rtcp_file = fopen("server.rtcp", FOPEN_WRITE_BINARY);
  }

  cur_pos = 0;
  packet_size = 64;
  number_of_packet = 0;
  while(1) {
    // change BUFFSIZE to be an incrementing value from 64 to 1450
    if(packet_size > 1450)
      packet_size = 725;
    readit = read(fd, buff, packet_size);
    if (readit < 0) {
      perror("file read");
      exit(1);
    }
    read_size = readit;
    //int buflen = readit;
    if (read_size == 0) break;
    //printf("about to protect\n");
#if 0
    sendit = 
      rtp_send_data(session,
		    cur_pos,
		    97,//pt
		    0,//m
		    0,//cc 
		    NULL, //csrc[],
		    buff,//data
		    read_size,//data_len
		    NULL,//*extn
		    0,
		    0);
#else
    {
      struct iovec iov[2];
      iov[0].iov_len = read_size % 48;
      if (iov[0].iov_len == 0) iov[0].iov_len = 1;
      iov[0].iov_base = buff;
      iov[1].iov_len = read_size - iov[0].iov_len;
      iov[1].iov_base = buff + iov[0].iov_len;

      sendit = rtp_send_data_iov(session, cur_pos, 97, 0, 0, NULL, 
				 iov, read_size > iov[0].iov_len ? 2 : 1,
				 NULL, 0, 0, 0);
    }
#endif
    if (sendit < 0) {
      printf("rtp_send_data error\n");
      exit(1);
    }
    if (do_rtcp)
      rtp_send_ctrl(session, cur_pos, NULL);
    printf("set timestamp = "U64", size %u\n", cur_pos, read_size);
		
    cur_pos += read_size; 
    packet_size++;
    number_of_packet++;
		
    //rtp_periodic();
    //rtp_send_ctrl(session,cur_pos,NULL);
    rtp_update(session);
    // Some sort of sleep here...
    usleep(2 * 1000);
  }
  
  printf("I've sent %d RTP packets!\n\n", number_of_packet);

  close(fd);
  if (rtcp_file != NULL) 
    fclose(rtcp_file);
  rtp_done(session);
  return 0;
}
コード例 #2
0
void *
os_sound_start_thread (void *_ca)
{
  int i;
  call_t *ca = (call_t *) _ca;
  struct timeval timeout;
  uint32_t rtp_ts, round;
  uint8_t mulaw_buffer[MULAW_BYTES * 16];
  int mulaw_buffer_pos;

#ifdef USE_PCM
  char data_out[MULAW_BYTES * 2 * 16];
#endif

  fprintf (stderr, "Sending and listening to ");
  fprintf (stderr, "%s port %d (local SSRC = 0x%08x)\n",
           rtp_get_addr (ca->rtp_session),
           rtp_get_rx_port (ca->rtp_session), rtp_my_ssrc (ca->rtp_session));

  round = 0;
  mulaw_buffer_pos = 0;

  while (ca->enable_audio != -1)
    {
      struct timeval t_beg;
      struct timeval t_end;
      struct timeval interval;

      gettimeofday (&t_beg, NULL);

      round++;
      /* original line rtp_ts = round * MULAW_MS; */
      rtp_ts = round * MULAW_BYTES;

      if (ca->local_sendrecv != _RECVONLY)
        {
          if (mulaw_buffer_pos < MULAW_BYTES * 4)
            {
              /* Send control packets */
              rtp_send_ctrl (ca->rtp_session, rtp_ts, NULL);

              /* Send data packets */
#ifdef USE_PCM
              i = read (ca->fd, data_out, MULAW_BYTES * 4);
              if (ca->local_sendrecv == _SENDRECV
                  || ca->local_sendrecv == _RECVONLY)
                {
              } else
                {
                  if (i < MULAW_BYTES * 4)
                    {
                      memset (data_out, 0, MULAW_BYTES * 4);
                      OSIP_TRACE (osip_trace
                                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
                                   "restarting: %i\n", i));
                      close (ca->fd);
                      /* send a wav file! */
                      ca->fd = open (ca->wav_file, O_RDONLY);
                      if (ca->fd < 0)
                        {
                          OSIP_TRACE (osip_trace
                                      (__FILE__, __LINE__, OSIP_INFO2, NULL,
                                       "Could not open wav file: %s\n",
                                       ca->wav_file));
                          ca->fd = -1;
                          break;
                        }
                      i = read (ca->fd, data_out, MULAW_BYTES * 4);
                    }
                }
              if (ca->payload == 8)     /* A-Law */
                alaw_enc (data_out, mulaw_buffer + mulaw_buffer_pos, i);
              if (ca->payload == 0)     /* Mu-Law */
                mulaw_enc (data_out, mulaw_buffer + mulaw_buffer_pos, i);
              i = i / 2;
              mulaw_buffer_pos = mulaw_buffer_pos + i;
#else
              memset (mulaw_buffer + mulaw_buffer_pos, 0, MULAW_BYTES * 2);
              i = read (ca->fd, mulaw_buffer + mulaw_buffer_pos, MULAW_BYTES * 2);      /* ?? */
              mulaw_buffer_pos = mulaw_buffer_pos + i;
#endif
            }

          i = 0;
          if (mulaw_buffer_pos >= MULAW_BYTES)
            {
              i = rtp_send_data (ca->rtp_session, rtp_ts, ca->payload,
                                 0, 0, 0, (char *) mulaw_buffer, MULAW_BYTES,
                                 0, 0, 0);
              memmove (mulaw_buffer, mulaw_buffer + MULAW_BYTES, MULAW_BYTES * 15);
              mulaw_buffer_pos = mulaw_buffer_pos - MULAW_BYTES;
            }
      } else
        {
          /* Send control packets */
          rtp_send_ctrl (ca->rtp_session, rtp_ts, NULL);
        }

      /* Receive control and data packets */
      timeout.tv_sec = 0;
      timeout.tv_usec = 0;
      i = rtp_recv (ca->rtp_session, &timeout, rtp_ts);
      /* State maintenance */
      rtp_update (ca->rtp_session);

      gettimeofday (&t_end, NULL);

      /* make a diff between t_beg and t_end */
      interval.tv_sec = t_end.tv_sec - t_beg.tv_sec;
      interval.tv_usec = t_end.tv_usec - t_beg.tv_usec;

      if (interval.tv_usec < 0)
        {
          interval.tv_usec += 1000000L;
          --interval.tv_sec;
        }
      interval.tv_usec = (MULAW_MS * 1000 - interval.tv_usec);
      if (interval.tv_usec < 0)
        {
          interval.tv_usec += 1000000L;
          --interval.tv_sec;
        }
      if (interval.tv_sec < 0)
        {
          interval.tv_sec = 0;
          interval.tv_usec = 0;
        }
      select (0, NULL, NULL, NULL, &interval);
    }
  return NULL;
}
コード例 #3
0
ファイル: toxav.c プロジェクト: subliun/toxcore
bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count,
                            uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error)
{
    uint64_t start_time = current_time_monotonic();
    uint64_t delta = start_time;
    
    LOGGER_DEBUG ("Starting time: %llu", start_time);
    
    TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
    ToxAVCall *call;

    if (m_friend_exists(av->m, friend_number) == 0) {
        rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
        goto END;
    }

    if (pthread_mutex_trylock(av->mutex) != 0) {
        rc = TOXAV_ERR_SEND_FRAME_SYNC;
        goto END;
    }

    call = call_get(av, friend_number);

    if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
        pthread_mutex_unlock(av->mutex);
        rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
        goto END;
    }

    if (call->audio_bit_rate == 0 ||
            !(call->msi_call->self_capabilities & msi_CapSAudio) ||
            !(call->msi_call->peer_capabilities & msi_CapRAudio)) {
        pthread_mutex_unlock(av->mutex);
        rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED;
        goto END;
    }

    pthread_mutex_lock(call->mutex_audio);
    pthread_mutex_unlock(av->mutex);

    if (pcm == NULL) {
        pthread_mutex_unlock(call->mutex_audio);
        rc = TOXAV_ERR_SEND_FRAME_NULL;
        goto END;
    }

    if (channels > 2) {
        pthread_mutex_unlock(call->mutex_audio);
        rc = TOXAV_ERR_SEND_FRAME_INVALID;
        goto END;
    }

    LOGGER_DEBUG("Initial checking took: %llu", current_time_monotonic() - delta);
    delta = current_time_monotonic();
    
    { /* Encode and send */
        if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
            pthread_mutex_unlock(call->mutex_audio);
            rc = TOXAV_ERR_SEND_FRAME_INVALID;
            goto END;
        }

        LOGGER_DEBUG("Encoder configuration took: %llu", current_time_monotonic() - delta);
        delta = current_time_monotonic();
        
        uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */

        sampling_rate = htonl(sampling_rate);
        memcpy(dest, &sampling_rate, sizeof(sampling_rate));
        int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
                              dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));

        LOGGER_DEBUG("Encoding took: %llu", current_time_monotonic() - delta);
        delta = current_time_monotonic();
        
        if (vrc < 0) {
            LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
            pthread_mutex_unlock(call->mutex_audio);
            rc = TOXAV_ERR_SEND_FRAME_INVALID;
            goto END;
        }

        if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate)) != 0) {
            LOGGER_WARNING("Failed to send audio packet");
            rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
        }
        
        LOGGER_DEBUG("Sending took: %llu", current_time_monotonic() - delta);
    }


    pthread_mutex_unlock(call->mutex_audio);

END:
    LOGGER_DEBUG ("End time: %llu Total: %llu", current_time_monotonic(), current_time_monotonic() - start_time);

    if (error)
        *error = rc;

    return rc == TOXAV_ERR_SEND_FRAME_OK;
}
コード例 #4
0
ファイル: toxav.c プロジェクト: subliun/toxcore
bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y,
                            const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error)
{
    TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
    ToxAVCall *call;

    if (m_friend_exists(av->m, friend_number) == 0) {
        rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
        goto END;
    }

    if (pthread_mutex_trylock(av->mutex) != 0) {
        rc = TOXAV_ERR_SEND_FRAME_SYNC;
        goto END;
    }

    call = call_get(av, friend_number);

    if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
        pthread_mutex_unlock(av->mutex);
        rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
        goto END;
    }

    if (call->video_bit_rate == 0 ||
            !(call->msi_call->self_capabilities & msi_CapSVideo) ||
            !(call->msi_call->peer_capabilities & msi_CapRVideo)) {
        pthread_mutex_unlock(av->mutex);
        rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED;
        goto END;
    }

    pthread_mutex_lock(call->mutex_video);
    pthread_mutex_unlock(av->mutex);

    if (y == NULL || u == NULL || v == NULL) {
        pthread_mutex_unlock(call->mutex_video);
        rc = TOXAV_ERR_SEND_FRAME_NULL;
        goto END;
    }

    if (vc_reconfigure_encoder(call->video.second, call->video_bit_rate * 1000, width, height) != 0) {
        pthread_mutex_unlock(call->mutex_video);
        rc = TOXAV_ERR_SEND_FRAME_INVALID;
        goto END;
    }

    { /* Encode */
        vpx_image_t img;
        img.w = img.h = img.d_w = img.d_h = 0;
        vpx_img_alloc(&img, VPX_IMG_FMT_I420, width, height, 0);

        /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes."
         * http://fourcc.org/yuv.php#IYUV
         */
        memcpy(img.planes[VPX_PLANE_Y], y, width * height);
        memcpy(img.planes[VPX_PLANE_U], u, (width / 2) * (height / 2));
        memcpy(img.planes[VPX_PLANE_V], v, (width / 2) * (height / 2));

        int vrc = vpx_codec_encode(call->video.second->encoder, &img,
                                   call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US);

        vpx_img_free(&img);

        if (vrc != VPX_CODEC_OK) {
            pthread_mutex_unlock(call->mutex_video);
            LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc));
            rc = TOXAV_ERR_SEND_FRAME_INVALID;
            goto END;
        }
    }

    ++call->video.second->frame_counter;

    { /* Send frames */
        vpx_codec_iter_t iter = NULL;
        const vpx_codec_cx_pkt_t *pkt;

        while ((pkt = vpx_codec_get_cx_data(call->video.second->encoder, &iter))) {
            if (pkt->kind == VPX_CODEC_CX_FRAME_PKT &&
                    rtp_send_data(call->video.first, pkt->data.frame.buf, pkt->data.frame.sz) < 0) {

                pthread_mutex_unlock(call->mutex_video);
                LOGGER_WARNING("Could not send video frame: %s\n", strerror(errno));
                rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
                goto END;
            }
        }
    }

    pthread_mutex_unlock(call->mutex_video);

END:

    if (error)
        *error = rc;

    return rc == TOXAV_ERR_SEND_FRAME_OK;
}
コード例 #5
0
static int handle_connection(RTSPContext *c)
{
    if (c->poll_entry == NULL) {
      //printf("c -> poll entry is null!! \n");
      return 0;
    }
    int len, ret;

    switch(c->state) {
    case HTTPSTATE_READY:
      //printf("http state ready \n");
      break;
    case RTSPSTATE_WAIT_REQUEST:
        /* timeout ? */
        if ((c->timeout - cur_time) < 0)
            return -1;
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
            return -1;

        /* no need to read if no events */
        if (!(c->poll_entry->revents & POLLIN))
            return 0;
        /* read the data */
    read_loop:
        len = recv(c->fd, c->buffer_ptr, 1, 0);
        if (len < 0) {
          printf("recv error\n");
          return -1;
        } else if (len == 0) {
            return -1;
        } else {
          /* search for end of request. */
          uint8_t *ptr;
          c->buffer_ptr += len;
          ptr = c->buffer_ptr;
          if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
            (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
            /* request found : parse it and reply */
            ret = rtsp_parse_request(c);
            if (ret < 0)
              return -1;
          } else if (ptr >= c->buffer_end) {
              /* request too long: cannot do anything */
            printf("request too long!! \n");
              return -1;
          } else goto read_loop;
        }
        break;

    case RTPSTATE_SEND_DATA:
        /* for packetized output, we consider we can always write (the
           input streams set the speed). It may be better to verify
           that we do not rely too much on the kernel queues */
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
            return -1;

        /* no need to read if no events */
        if (!(c->poll_entry->revents & POLLOUT))
            return 0;

        if (rtp_send_data(c) < 0)
            return -1;
        break;

    case RTSPSTATE_SEND_REPLY:
        //printf("rtspstate send reply \n");
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
            goto close_connection;
        /* no need to write if no events */
        if (!(c->poll_entry->revents & POLLOUT))
            return 0;
        printf("send! reply \n");
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
        if (len < 0) {
            printf("send error TT! \n");
            goto close_connection;
        } else {
            printf("send reply success!! len = %d \n", len);
            c->buffer_ptr += len;
            if (c->buffer_ptr >= c->buffer_end) {
                /* all the buffer was sent : wait for a new request */
                av_freep(&c->pb_buffer);
                start_wait_request(c);
            }
        }
        break;
    case RTSPSTATE_SEND_PACKET:
        printf("rtsp send packet! \n");
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
            av_freep(&c->pb_buffer);
            return -1;
        }
        /* no need to write if no events */
        if (!(c->poll_entry->revents & POLLOUT))
            return 0;
        len = send(c->fd, c->buffer_ptr,
                    c->buffer_end - c->buffer_ptr, 0);
        if (len < 0) {
          /* error : close connection */
          av_freep(&c->pb_buffer);
          return -1;
        } else {
            c->buffer_ptr += len;
            if (c->buffer_ptr >= c->buffer_end) {
                // all the buffer was sent : wait for a new request
                av_freep(&c->buffer);
                c->state = RTSPSTATE_WAIT_REQUEST;
            }
        }
        break;
    default:
        return -1;
    }
    return 0;

close_connection:
    printf("close connection!\n");
    av_freep(&c->pb_buffer);
    return -1;
}