예제 #1
0
파일: client.c 프로젝트: Jaminy/resiprocate
static void
nr_stun_send_test( Socket myFd, StunAddress4* dest,
              StunAtrString* username, StunAtrString* password,
              int testNum)
{
   int r,_status;
   nr_stun_message *msg;
   nr_stun_client_stun_binding_request_params params;
   Data password2;

   assert( dest->addr != 0 );
   assert( dest->port != 0 );

   params.username = username->value;
   password2.data = (UCHAR*)password->value;
   password2.len = password->sizeValue;
   params.password = &password2;

   switch (stun_mode) {
   default:
       switch (auth_rule) {
       case NR_STUN_AUTH_RULE_OPTIONAL:
           if ((r=nr_stun_build_req_no_auth(&params, &msg)))
               ABORT(r);
           break;
       case NR_STUN_AUTH_RULE_SHORT_TERM:
           if ((r=nr_stun_build_req_st_auth(&params, &msg)))
               ABORT(r);
           break;
       case NR_STUN_AUTH_RULE_LONG_TERM:
           if ((r=nr_stun_build_req_lt_auth(&params, &msg)))
               ABORT(r);
           break;
       }
       break;
#ifdef USE_STUND_0_96
   case NR_STUN_MODE_STUND_0_96:
       if ((r=nr_stun_build_req_stund_0_96(0, &msg)))
           ABORT(r);
       break;
#endif /* USE_STUND_0_96 */
   }

   if ((r=nr_stun_encode_message(msg)))
       ABORT(r);

   r_log(NR_LOG_STUN, LOG_DEBUG, "About to send msg of len %d to %s",msg->length,nr_ip4toa(dest));

   sendMessage( myFd, (char*)msg->buffer, msg->length, dest->addr, dest->port);

   _status=0;
 abort:
//   return _status;
   return;
}
예제 #2
0
/* TODO([email protected]): We currently don't support channels.
   We might in the future. Mozilla bug 857736 */
int nr_turn_client_send_indication(nr_turn_client_ctx *ctx,
                                   const UCHAR *msg, size_t len,
                                   int flags, nr_transport_addr *remote_addr)
{
  int r,_status;
  nr_stun_client_send_indication_params params = { { 0 } };
  nr_stun_message *ind = 0;

  if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
    ABORT(R_FAILED);

  r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Send indication len=%zu",
        ctx->label, len);

  if ((r=nr_turn_client_ensure_perm(ctx, remote_addr)))
    ABORT(r);

  if ((r=nr_transport_addr_copy(&params.remote_addr, remote_addr)))
    ABORT(r);

  params.data.data = (UCHAR*)msg;
  params.data.len = len;

  if ((r=nr_stun_build_send_indication(&params, &ind)))
    ABORT(r);

  if ((r=nr_stun_encode_message(ind)))
    ABORT(r);

  if ((r=nr_socket_sendto(ctx->sock,
                          ind->buffer, ind->length, flags,
                          &ctx->turn_server_addr))) {
    r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Failed sending send indication",
          ctx->label);
    ABORT(r);
  }

  _status=0;
abort:
  RFREE(ind);
  return(_status);
}
예제 #3
0
int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
                                     nr_stun_message *req,
                                     int flags)
{
  int r,_status;

  if ((r=nr_stun_encode_message(req)))
    ABORT(r);

  if ((r=nr_socket_sendto(ctx->sock,
                          req->buffer, req->length, flags,
                          &ctx->turn_server_addr))) {
    r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Failed sending request",
          ctx->label);
    ABORT(r);
  }

  _status=0;
abort:
  return(_status);
}
예제 #4
0
static int nr_stun_client_send_request(nr_stun_client_ctx *ctx)
  {
    int r,_status;
    char string[256];

    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
        ABORT(R_NOT_PERMITTED);

    r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Sending check request (my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,ctx->peer_addr.as_string);

    if (ctx->request == 0) {
        switch (ctx->mode) {
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH:
            ctx->params.stun_binding_request.nonce = ctx->nonce;
            ctx->params.stun_binding_request.realm = ctx->realm;
            assert(0);
            ABORT(R_INTERNAL);
            /* TODO([email protected]): Need to implement long-term auth for binding
               requests */
            if ((r=nr_stun_build_req_lt_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH:
            if ((r=nr_stun_build_req_st_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH:
            if ((r=nr_stun_build_req_no_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_KEEPALIVE:
            if ((r=nr_stun_build_keepalive(&ctx->params.stun_keepalive, &ctx->request)))
                ABORT(r);
            break;
#ifdef USE_STUND_0_96
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96:
            if ((r=nr_stun_build_req_stund_0_96(&ctx->params.stun_binding_request_stund_0_96, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_STUND_0_96 */

#ifdef USE_ICE
        case NR_ICE_CLIENT_MODE_USE_CANDIDATE:
            if ((r=nr_stun_build_use_candidate(&ctx->params.ice_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_ICE_CLIENT_MODE_BINDING_REQUEST:
            if ((r=nr_stun_build_req_ice(&ctx->params.ice_binding_request, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_ICE */

#ifdef USE_TURN
        case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST:
            if ((r=nr_stun_build_allocate_request(&ctx->auth_params, &ctx->params.allocate_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_REFRESH_REQUEST:
            if ((r=nr_stun_build_refresh_request(&ctx->auth_params, &ctx->params.refresh_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_PERMISSION_REQUEST:
            if ((r=nr_stun_build_permission_request(&ctx->auth_params, &ctx->params.permission_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_SEND_INDICATION:
            if ((r=nr_stun_build_send_indication(&ctx->params.send_indication, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_TURN */

        default:
            assert(0);
            ABORT(R_FAILED);
            break;
        }
    }

    if (ctx->request->length == 0) {
        if ((r=nr_stun_encode_message(ctx->request)))
            ABORT(r);
    }

    snprintf(string, sizeof(string)-1, "STUN-CLIENT(%s): Sending to %s ", ctx->label, ctx->peer_addr.as_string);
    r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)ctx->request->buffer, ctx->request->length);

    assert(ctx->my_addr.protocol==ctx->peer_addr.protocol);

    if(r=nr_socket_sendto(ctx->sock, ctx->request->buffer, ctx->request->length, 0, &ctx->peer_addr))
      ABORT(r);

    ctx->request_ct++;

    if (NR_STUN_GET_TYPE_CLASS(ctx->request->header.type) == NR_CLASS_INDICATION) {
        /* no need to set the timer because indications don't receive a
         * response */
    }
    else {
        if (ctx->request_ct >= ctx->maximum_transmits) {
          /* Reliable transport only get here once. Unreliable get here for
           * their final timeout. */
          ctx->timeout_ms += ctx->maximum_transmits_timeout_ms;
        }
        else if (ctx->timeout_ms) {
          /* exponential backoff */
          ctx->timeout_ms *= ctx->retransmission_backoff_factor;
        }
        else {
          /* initial timeout unreliable transports */
          ctx->timeout_ms = ctx->rto_ms;
        }

        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Next timer will fire in %u ms",ctx->label, ctx->timeout_ms);

        gettimeofday(&ctx->timer_set, 0);

        assert(ctx->timeout_ms);
        NR_ASYNC_TIMER_SET(ctx->timeout_ms, nr_stun_client_timer_expired_cb, ctx, &ctx->timer_handle);
    }

    _status=0;
  abort:
    if (_status) {
      nr_stun_client_failed(ctx);
    }
    return(_status);
  }
예제 #5
0
static void s_cb(int s, int how, void *cb_arg)
  {
#if 0
    nr_socket *sock = (nr_socket*)cb_arg;
    UCHAR buf2[4096];
    size_t len;
    nr_transport_addr addr2;
    int r;
    StunMessage req;
    StunMessage res;
    //StunAddress4 from;

    fprintf(stderr,"TURN_SERVER_UTIL: SERVER CB\n");

    if(r=nr_socket_recvfrom(sock,buf2,sizeof(buf2),&len,0,&addr2)){
      fprintf(stderr,"Error in recvfrom\n");
      exit(1);
    }

    memset(&req, 0, sizeof(req));
    memset(&res, 0, sizeof(res));
    //memset(&from, 0, sizeof(from));
    //from.addr = ntohl(addr2.u.addr4.sin_addr.s_addr);
    //from.port = ntohs(addr2.u.addr4.sin_port);

    if ((r=nr_stun_parse_message((char*)buf2, len, &req))) {
      fprintf(stderr,"Error in nr_stun_parse_message\n");
      exit(1);
    }

    if ((r=nr_stun_process_request(&req, buf2, len, &addr2, 0, 0, &res))) {
        /* failure is expected because the server code doesn't support TURN */
        if (r!=R_FAILED) {
            fprintf(stderr,"Failed to process message!\n");
            exit(1);
        }
        fprintf(stderr,"TURN_SERVER_UTIL: No problem with parse failure ... process TURN in test server code\n");
    }

    if (!nr_is_stun_message((char*)buf2, len)) {
        fprintf(stderr,"TURN_SERVER_UTIL: not a STUN/TURN message\n");
        /* instead of sending to remoteAddress, just echo the content back
         * for the purposes of our tests */
        goto send;
    }

    res.hasFingerprint = 1;

    switch (req.msgHdr.msgType) {
    case AllocateRequestMsg:
       if (! req.hasNonce) {
           fprintf(stderr, "Received AllocateRequestMsg #1\n");
           assert(!req.hasMessageIntegrity);
/* TODO: what about username: does it go into the req or not? spec not clear */
           res.msgHdr.msgType = AllocateErrorResponseMsg;
           res.hasUsername = 0;
           res.hasNonce = 1;
           strcpy(res.nonce, nonce);
           res.hasRealm = 1;
           strcpy(res.realm, "REALM");
           res.hasErrorCode = 1;
           res.errorCode.errorClass = 4;
           res.errorCode.number = 35;
       }
       else {
           fprintf(stderr, "Received AllocateRequestMsg #2\n");
           assert(req.hasUsername);
           assert(req.hasRealm);
           assert(req.hasNonce);
           assert(req.hasMessageIntegrity);
           res.msgHdr.msgType = AllocateResponseMsg;
           res.hasUsername = 1;
           res.hasMessageIntegrity = 1;
           strcpy(res.username, req.username);
#if 0
//TODO: this is totally broken, but TURN is changing and so
//TODO: we'll need to take another pass at all this code
//TODO: anyhow, so leave it broken for now
           res.hasRelayAddress = 1;
           res.relayAddress.family = IPv4Family;
           res.relayAddress.ipv4.addr = from.addr;
           res.relayAddress.ipv4.port = from.port;
           res.hasXorMappedAddress = 1;
           res.xorMappedAddress.family = IPv4Family;
           res.xorMappedAddress.ipv4.addr = from.addr;
           res.xorMappedAddress.ipv4.port = from.port;
#endif
       }
       break;
    case SendIndicationMsg:
       fprintf(stderr, "Received SendIndicationMsg\n");
       assert(req.hasRemoteAddress);

       /* pretend to send empty UDP packet to remoteAddress per the
        * TURN spec and to wait for a DataIndication resonse */
       fprintf(stderr, "Sending UDP packet to REMOTE-ADDRESS...\n");
       fprintf(stderr, "Waiting for response from REMOTE-ADDRESS...\n");

       /* ok, this is an indication, so formally there is no "response",
        * but we're going to send a data indication to it, so just pretend
        * that it's a formal response */
       res.msgHdr.msgType = DataIndicationMsg;
       res.hasRemoteAddress = 1;
       nr_transport_addr_copy(&res.remoteAddress, &req.remoteAddress);

       break;
    case SetActiveDestRequestMsg:
       fprintf(stderr, "Received SetActiveDestRequestMsg\n");
       assert(req.hasRemoteAddress);
 
       res.msgHdr.msgType = SetActiveDestResponseMsg;
       break;
    default:
       assert(0);
       break;
    }

   memset(&buf2, 0, sizeof(buf2));

   if ((r=nr_stun_encode_message(STUN_MODE_STUN, &res, (char*)buf2, STUN_MAX_MESSAGE_SIZE, &pass, (unsigned int*)&len))) {
      fprintf(stderr,"Error encoding TURN response\n");
      exit(1);
    }

 send:
   fprintf(stderr,"Sending response to %s\n", addr2.as_string);
   if(r=nr_socket_sendto(sock,buf2,len,0,&addr2)) {
      fprintf(stderr,"Error sending TURN response\n");
      exit(1);
    }

    NR_ASYNC_WAIT(s, how, s_cb, cb_arg);
#else
UNIMPLEMENTED;
#endif
  }
예제 #6
0
static int nr_stun_client_send_request(nr_stun_client_ctx *ctx)
{
    int r,_status;
    char string[256];

    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
        ABORT(R_NOT_PERMITTED);

    r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Sending(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,ctx->peer_addr.as_string);

    if (ctx->request == 0) {
        switch (ctx->mode) {
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH:
            ctx->params.stun_binding_request.nonce = ctx->nonce;
            ctx->params.stun_binding_request.realm = ctx->realm;
            if ((r=nr_stun_build_req_lt_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH:
            if ((r=nr_stun_build_req_st_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH:
            if ((r=nr_stun_build_req_no_auth(&ctx->params.stun_binding_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_STUN_CLIENT_MODE_KEEPALIVE:
            if ((r=nr_stun_build_keepalive(&ctx->params.stun_keepalive, &ctx->request)))
                ABORT(r);
            break;
#ifdef USE_STUND_0_96
        case NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96:
            if ((r=nr_stun_build_req_stund_0_96(&ctx->params.stun_binding_request_stund_0_96, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_STUND_0_96 */

#ifdef USE_ICE
        case NR_ICE_CLIENT_MODE_USE_CANDIDATE:
            if ((r=nr_stun_build_use_candidate(&ctx->params.ice_use_candidate, &ctx->request)))
                ABORT(r);
            break;
        case NR_ICE_CLIENT_MODE_BINDING_REQUEST:
            if ((r=nr_stun_build_req_ice(&ctx->params.ice_binding_request, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_ICE */

#ifdef USE_TURN
        case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST1:
            if ((r=nr_stun_build_allocate_request1(&ctx->params.allocate_request1, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST2:
            if ((r=nr_stun_build_allocate_request2(&ctx->params.allocate_request2, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_SEND_INDICATION:
            if ((r=nr_stun_build_send_indication(&ctx->params.send_indication, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_SET_ACTIVE_DEST_REQUEST:
            if ((r=nr_stun_build_set_active_dest_request(&ctx->params.set_active_dest_request, &ctx->request)))
                ABORT(r);
            break;
        case NR_TURN_CLIENT_MODE_DATA_INDICATION:
            if ((r=nr_stun_build_data_indication(&ctx->params.data_indication, &ctx->request)))
                ABORT(r);
            break;
#endif /* USE_TURN */

        default:
            assert(0);
            ABORT(R_FAILED);
            break;
        }
    }

    if (ctx->request->length == 0) {
        if ((r=nr_stun_encode_message(ctx->request)))
            ABORT(r);
    }

    snprintf(string, sizeof(string)-1, "STUN-CLIENT(%s): Sending to %s ", ctx->label, ctx->peer_addr.as_string);
    r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)ctx->request->buffer, ctx->request->length);

    if(r=nr_socket_sendto(ctx->sock, ctx->request->buffer, ctx->request->length, 0, &ctx->peer_addr))
        ABORT(r);

    ctx->request_ct++;

    if (NR_STUN_GET_TYPE_CLASS(ctx->request->header.type) == NR_CLASS_INDICATION) {
        /* no need to set the timer because indications don't receive a
         * response */
    }
    else {
        if (ctx->request_ct < ctx->maximum_transmits) {
            ctx->timeout_ms *= ctx->retransmission_backoff_factor;
            ctx->timeout_ms += ctx->rto_ms;
        }
        else {
            ctx->timeout_ms += ctx->final_retransmit_backoff_ms;
        }

        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Next timer will fire in %u ms",ctx->label, ctx->timeout_ms);

        gettimeofday(&ctx->timer_set, 0);

        NR_ASYNC_TIMER_SET(ctx->timeout_ms, nr_stun_client_timer_expired_cb, ctx, &ctx->timer_handle);
    }

    _status=0;
abort:
    if (_status) {
        ctx->state=NR_STUN_CLIENT_STATE_FAILED;
    }
    return(_status);
}
예제 #7
0
파일: server.c 프로젝트: Jaminy/resiprocate
int
nr_stun_server_process(StunServerInfo* info)
{
   int r,_status;
   char msg[NR_STUN_MAX_MESSAGE_SIZE];
   int msgLen = sizeof(msg);

   char ok = 0;
   char recvAltIp =0;
   char recvAltPort = 0;

   fd_set fdSet;
   Socket maxFd=0;
   struct timeval tv;
   nr_stun_message *req;
   nr_stun_message *resp;
   Data password = { (UCHAR*)"hello", 5 };
   nr_transport_addr from2;

   FD_ZERO(&fdSet);
   FD_SET(info->myFd,&fdSet);
   if ( info->myFd >= maxFd ) maxFd=info->myFd+1;

   tv.tv_sec = 1;
   tv.tv_usec = 0;

   int e = select( maxFd, &fdSet, NULL,NULL, &tv );
   if (e < 0)
   {
      r_log_e(NR_LOG_STUN, LOG_WARNING, "Error on select");
   }
   else if (e >= 0)
   {
      StunAddress4 from;

      if (FD_ISSET(info->myFd,&fdSet))
      {
         r_log(NR_LOG_STUN, LOG_DEBUG, "received on A1:P1");
         recvAltIp = 0;
         recvAltPort = 0;
         ok = 1;
         if (getMessage( info->myFd, msg, &msgLen, &from.addr, &from.port))
             ok = 0;
      }
      else
      {
         goto done;
      }

      if ( !ok )
      {
         r_log(NR_LOG_STUN, LOG_DEBUG, "Get message did not return a valid message");
         goto done;
      }

      r_log(NR_LOG_STUN, LOG_DEBUG, "Got request (len=%u) from %s",msgLen,nr_ip4toa(&from));

      if ( msgLen <= 0 )
      {
         goto done;
      }


      if ((r=nr_stun_message_create2(&req, (UCHAR*)msg, msgLen))) {
        fprintf(stderr,"Error in nr_stun_message_create2\n");
        exit(1);
      }
     
      if ((r=nr_stun_decode_message(req, returnpassword, &password))) {
        fprintf(stderr,"Error in nr_stun_parse_message\n");
        exit(1);
      }

      if ((r=nr_stun_message_create(&resp))) {
        fprintf(stderr,"Error in nr_stun_message_create\n");
        exit(1);
      }

      nr_ip4_port_to_transport_addr(from.addr, from.port, IPPROTO_UDP, &from2);

      if ((r=nr_stun_receive_message(0, req))) {
         r_log(NR_LOG_STUN, LOG_DEBUG, "Failed to receive message");
         nr_stun_form_error_response(req, resp, 400, "Bad Message");
      }
      else if (alternate_server && from.addr != info->myAddr.addr) {
/* NOTE: this code is broken because we don't want 'from', we want 'to',
 * but UNIX doesn't provide a way to easily get that information, so
 * the -a flag only works when the client and server reside on the
 * same machine */
          /* send ALTERNATE-SERVER */
          nr_transport_addr alternate_server;
          nr_stun_form_error_response(req, resp, 300, "Alternate Server");
          nr_ip4_port_to_transport_addr(info->myAddr.addr, info->myAddr.port, IPPROTO_UDP, &alternate_server);
          nr_stun_message_add_alternate_server_attribute(resp, &alternate_server);
      }
      else if ((r=nr_stun_process_request(req,resp))) {
         r_log(NR_LOG_STUN, LOG_DEBUG, "Failed to process request");
         /* continue, even though failed to parse message, to send error message */
      }
      else {
          nr_stun_form_success_response(req, &from2, &password, resp);
      }

      if ((r=nr_stun_encode_message(resp)))
      {
          /* ignore this failure */
      }
      else if (from.addr != 0 && from.port != 0)
      {
         if ( info->myFd != INVALID_SOCKET )
         {
            sendMessage(info->myFd, (char*)resp->buffer, resp->length, from.addr, from.port);
         }
      }
   }

 done:
   _status=0;
// abort:
   return _status;
}