Beispiel #1
0
struct telnet_svc * telnet_svc_init(int port)
{  
	struct telnet_svc * tn = &telnet_svc;
	int th;

	if (port == 0)
		port = 23; /* use default TELNET srvice port */

	tn->svc = tcp_alloc();
	tn->tp = NULL;
	tcp_bind(tn->svc, INADDR_ANY, htons(port));

	if (tcp_listen(tn->svc, 1) != 0) {
		INF("Can't register the TCP listner!");
		return NULL;
	}

	tn->rx.nonempty_flag = thinkos_flag_alloc();
	tn->rx.nonfull_flag = thinkos_flag_alloc();
	tn->rx.head = 0;
	tn->rx.tail = 0;

	th = thinkos_thread_create_inf((void *)telnet_input_task, (void *)tn, 
								   &telnet_srv_inf);
	(void)th;
								
	INF("TELNET TCP input thread=%d", th);

	return tn;
}
Beispiel #2
0
/*
 * Create socket and start connection to another host.
 * ! not wait until connection established.
 * \return socket in connection state
 * \return      = NULL, or SExxx - some error
 */
tcp_socket_t *tcp_connect_start (ip_t *ip,  ip_addr ipaddr, unsigned short port)
{
	tcp_socket_t *s;

	tcp_debug ("tcp_connect to port %u\n", port);
	if (ipaddr.val == 0)
		return 0;
	mutex_lock (&ip->lock);

	s = tcp_alloc (ip);
	if (s == 0){
        mutex_unlock (&ip->lock);
	    return 0;
	}
	
	s->remote_ip.val = ipaddr.val;
	s->remote_port = port;
	if (s->local_port == 0) {
		s->local_port = tcp_new_port (ip);
	}
    mutex_unlock (&ip->lock);
    tcp_socket_t* res = tcp_connect_restart(s);
    if (SEANYERROR(res)){
        mem_free(s);
    }
    return res;
}
Beispiel #3
0
/*
 * Set the state of the connection to be LISTEN, which means that it
 * is able to accept incoming connections. The protocol control block
 * is reallocated in order to consume less memory. Setting the
 * connection to LISTEN is an irreversible process.
 */
tcp_socket_t *tcp_listen (ip_t *ip, unsigned char *ipaddr,
	unsigned short port)
{
	tcp_socket_t *s, *cs;
	ip_addr targetip;
	

	if (ipaddr) {
	    targetip = ipadr_4ucs(ipaddr);
	}
	else
	    targetip.val = 0;

	s = tcp_alloc (ip);
	if (s == 0) {
		return 0;
	}

	/* Bind the connection to a local portnumber and IP address. */
	mutex_lock (&ip->lock);
	if (port == 0) {
		port = tcp_new_port (ip);
	}
	tcp_debug ("tcp_listen: port %u\n", port);

	/* Check if the address already is in use. */
	for (cs = ip->tcp_listen_sockets; cs != 0; cs = cs->next) {
		if (cs->local_port == port) {
			if ( ipadr_is_same(targetip.var, cs->local_ip) ) {
				mutex_unlock (&ip->lock);
				mem_free (s);
				return 0;
			}
		}
	}
	for (cs = ip->tcp_sockets; cs != 0; cs = cs->next) {
		if (cs->local_port == port) {
			if (ipadr_is_same(targetip.var, cs->local_ip) ) {
				mutex_unlock (&ip->lock);
				mem_free (s);
				return 0;
			}
		}
	}

	if ( ipadr_not0(targetip.var) ) {
		s->local_ip = targetip.var;
	}
	s->local_port = port;
	s->state = LISTEN;
    buf_queueh_init(&s->inq, sizeof(s->queue));

	tcp_list_add (&ip->tcp_listen_sockets, s);
	mutex_unlock (&ip->lock);
	return s;
}
Beispiel #4
0
/*
 * Connect to another host. Wait until connection established.
 * Return 1 on success, 0 on error.
 */
tcp_socket_t *
tcp_connect (ip_t *ip, unsigned char *ipaddr, unsigned short port)
{
	tcp_socket_t *s;
	unsigned long optdata;

	tcp_debug ("tcp_connect to port %u\n", port);
	if (ipaddr == 0)
		return 0;
	mutex_lock (&ip->lock);

	s = tcp_alloc (ip);
	memcpy (s->remote_ip, ipaddr, 4);
	s->remote_port = port;
	if (s->local_port == 0) {
		s->local_port = tcp_new_port (ip);
	}
	s->lastack = s->snd_nxt - 1;
	s->snd_lbb = s->snd_nxt - 1;
	s->snd_wnd = TCP_WND;
	s->ssthresh = s->mss * 10;
	s->state = SYN_SENT;

	/* Build an MSS option */
	optdata = HTONL (((unsigned long)2 << 24) |
		((unsigned long)4 << 16) |
		(((unsigned long)s->mss / 256) << 8) |
		(s->mss & 255));

	if (! tcp_enqueue (s, 0, 0, TCP_SYN, (unsigned char*) &optdata, 4)) {
		mem_free (s);
		mutex_unlock (&ip->lock);
		return 0;
	}
	tcp_list_add (&ip->tcp_sockets, s);
	tcp_output (s);
	mutex_unlock (&ip->lock);

	mutex_lock (&s->lock);
	for (;;) {
		mutex_wait (&s->lock);
		if (s->state == ESTABLISHED) {
			mutex_unlock (&s->lock);
			return s;
		}
		if (s->state == CLOSED) {
			mutex_unlock (&s->lock);
			mem_free (s);
			return 0;
		}
	}
}
Beispiel #5
0
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct tcp_iphdr_s *buf)
{
  FAR struct tcp_conn_s *conn = tcp_alloc();
  if (conn)
    {
      /* Fill in the necessary fields for the new connection. */

      conn->rto           = TCP_RTO;
      conn->timer         = TCP_RTO;
      conn->sa            = 0;
      conn->sv            = 4;
      conn->nrtx          = 0;
      conn->lport         = buf->destport;
      conn->rport         = buf->srcport;
      conn->mss           = TCP_INITIAL_MSS;
      net_ipaddr_copy(conn->ripaddr, net_ip4addr_conv32(buf->srcipaddr));
      conn->tcpstateflags = TCP_SYN_RCVD;

      tcp_initsequence(conn->sndseq);
      conn->unacked       = 1;
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
      conn->expired       = 0;
      conn->isn           = 0;
      conn->sent          = 0;
#endif

      /* rcvseq should be the seqno from the incoming packet + 1. */

      memcpy(conn->rcvseq, buf->seqno, 4);

#ifdef CONFIG_NET_TCP_READAHEAD
      /* Initialize the list of TCP read-ahead buffers */

      IOB_QINIT(&conn->readahead);
#endif

#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
      /* Initialize the write buffer lists */

      sq_init(&conn->write_q);
      sq_init(&conn->unacked_q);
#endif

      /* And, finally, put the connection structure into the active list.
       * Interrupts should already be disabled in this context.
       */

      dq_addlast(&conn->node, &g_active_tcp_connections);
    }

  return conn;
}
Beispiel #6
0
static int psock_tcp_alloc(FAR struct socket *psock)
{
  /* Allocate the TCP connection structure */

  FAR struct tcp_conn_s *conn = tcp_alloc(psock->s_domain);
  if (!conn)
    {
      /* Failed to reserve a connection structure */

      return -ENOMEM;
    }

  /* Set the reference count on the connection structure.  This reference
   * count will be incremented only if the socket is dup'ed
   */

  DEBUGASSERT(conn->crefs == 0);
  conn->crefs = 1;

  /* Save the pre-allocated connection in the socket structure */

  psock->s_conn = conn;
  return OK;
}
Beispiel #7
0
int __attribute__((noreturn)) dcc_tcp_read_task(armice_ctrl_t * ctrl, int id)
{
	struct dcc_tcp_parm tcp_parm;
	jtag_arm_dcc_t * arm_dcc = &ctrl->arm_dcc;
	uint32_t buf[DCC_TCP_BUF_SIZE / sizeof(uint32_t)];
	struct tcp_pcb * tp;
	struct tcp_pcb * mux;
	int th;
	int n;
	int port = 1001;

	for (;;) {
		mux = tcp_alloc();

		DCC_LOG1(LOG_TRACE, "mux=%p", mux);

		tcp_bind(mux, INADDR_ANY, htons(port));

		if (tcp_listen(mux, 1) != 0) {
			DCC_LOG1(LOG_WARNING, "<%d> tcp_listen()", id);
			break;
		}

		if ((tp = tcp_accept(mux)) == NULL) {
			DCC_LOG(LOG_ERROR, "tcp_accept().");
			break;
		}

		tcp_close(mux);

		DCC_LOG2(LOG_TRACE, "%I:%d accepted.", 
				 tp->t_faddr, ntohs(tp->t_fport));
	
		jtag_arm_dcc_open(arm_dcc);

		tcp_parm.tp = tp;
		tcp_parm.arm_dcc = arm_dcc;

		th = uthread_create(dcc_write_stack, sizeof(dcc_write_stack), 
							(uthread_task_t)dcc_tcp_write_task, 
							(void *)&tcp_parm, 0, NULL); 
		if (th < 0) {
			DCC_LOG(LOG_ERROR, "uthread_create() fail!"); 
			jtag_arm_dcc_close(arm_dcc);
			tcp_close(tp);
			DCC_LOG2(LOG_TRACE, "%I:%d closed.", 
					 tp->t_faddr, ntohs(tp->t_fport));
			break;
		}

		for (;;) {
			if ((n = jtag_arm_dcc_read(arm_dcc, buf, sizeof(buf), 500)) < 0) {
				DCC_LOG1(LOG_WARNING, "jtag_arm_dcc_read(): %d", n); 
				break;
			}

			DCC_LOG1(LOG_MSG, "jtag_arm_dcc_read(): %d", n); 

			if (n == 0) {
				continue;
			}

			if ((n = tcp_send(tp, buf, n, 0)) < 0) {
				DCC_LOG2(LOG_TRACE, "%I:%d error.", 
						 tp->t_faddr, ntohs(tp->t_fport));
				break;
			}
		} 

		jtag_arm_dcc_close(arm_dcc);

		DCC_LOG2(LOG_TRACE, "%I:%d closed.", tp->t_faddr, ntohs(tp->t_fport));

		tcp_close(tp);

		uthread_join(th);
	}

	for(;;);
}
Beispiel #8
0
int rtsp_connect(struct rtsp_client * rtsp, const char * host,
		unsigned int port, const char * mrl)
{
	struct tcp_pcb * tp;
	in_addr_t host_addr;

	if (!inet_aton(host, (struct in_addr *)&host_addr)) {
		return -1;
	}

	if ((tp = tcp_alloc()) == NULL) {
		ERR("can't allocate socket!");
		return -1;
	}

	if (port == 0) {
		port = rtsp->port;
		if (port == 0)
			port = 554;
	}

	INF("RTSP://%s:%d/%s", host, port, mrl);

	if (tcp_connect(tp, host_addr, htons(port)) < 0) {
		ERR("can't connect to host!");
		tcp_close(tp);
		return -1;
	}

	rtsp->tcp = tp;
	rtsp->port = port;
	rtsp->host_addr = host_addr;
	rtsp->rtp.faddr = host_addr;
	rtsp->cseq = 1;

	strcpy(rtsp->host_name, host);
	strcpy(rtsp->media_name, mrl);

	if (rtsp_request_options(rtsp) < 0) {
		ERR("rtsp_request_options() failed!");
		return -1;
	}

	if (rtsp_request_describe(rtsp) < 0) {
		ERR("rtsp_request_describe() failed!");
		return -1;
	}

	if (rtsp_sdp_decode(rtsp) < 0) {
		ERR("rtsp_sdp_decode() failed!");
		return -1;
	}

	INF("Track:\"%s\"", rtsp->track_name);

	if (rtsp_request_setup(rtsp) < 0) {
		ERR("rtsp_request_setup() failed!");
		return -1;
	}

	if (rtsp_request_play(rtsp) < 0) {
		ERR("rtsp_request_play() failed!");
		return -1;
	}

	return 0;
}
Beispiel #9
0
tcp_socket_t *tcp_accept_until (tcp_socket_t *s
                                , scheduless_condition waitfor, void* waitarg)
{
	tcp_socket_t *ns;
	buf_t *p;
	ip_hdr_t *iph;
	tcp_hdr_t *h;
	unsigned long optdata;
    int ok = tcp_lock_avail(s, (1<<LISTEN)
                              , waitfor, waitarg);
    if (ok != 0){
        if (s->state != LISTEN){
            tcp_debug ("tcp_accept: called in invalid state\n");
            return (tcp_socket_t *)SEINVAL;
        }
        if (ok == -1)
            return 0;
        return (tcp_socket_t *)ok;
    }

	/* Create a new PCB, and respond with a SYN|ACK.
	 * If a new PCB could not be created (probably due to lack of memory),
	 * we don't do anything, but rely on the sender will retransmit
	 * the SYN at a time when we have more memory available. */
	mutex_lock (&s->ip->lock);
	ns = tcp_alloc (s->ip);
	if (ns == 0) {
        mutex_unlock (&s->lock);
		++(s->ip->tcp_in_discards);
		mutex_unlock (&s->ip->lock);
        tcp_debug ("tcp_accept: could not allocate PCB\n");
		return (tcp_socket_t *)SENOMEM;
	}
    p = tcp_queue_get (s);

	h = (tcp_hdr_t*) p->payload;
	iph = ((ip_hdr_t*) p->payload) - 1;

	/* Set up the new PCB. */
	ns->local_ip = iph->dest.var;
	ns->local_port = s->local_port;
	ns->remote_ip  = iph->src;
	ns->remote_port = h->src;
	ns->state = SYN_RCVD;
	ns->rcv_nxt = s->ip->tcp_input_seqno + 1;
	ns->snd_wnd = h->wnd;
	ns->ssthresh = ns->snd_wnd;
	ns->snd_wl1 = s->ip->tcp_input_seqno;
	ns->ip = s->ip;
    mutex_unlock (&s->lock);

	/* Register the new PCB so that we can begin receiving
	 * segments for it. */
	tcp_list_add (&s->ip->tcp_sockets, ns);

	/* Parse any options in the SYN. */
	tcp_parseopt (ns, h);

	/* Build an MSS option. */
	optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) |
		(((unsigned long)ns->mss / 256) << 8) | (ns->mss & 255));
	buf_free (p);

	/* Send a SYN|ACK together with the MSS option.
	 * there is impossible fail of tcp_enqueue_option4
	 * */
	tcp_enqueue_option4 (ns, TCP_SYN | TCP_ACK, optdata);
#if TCP_LOCK_STYLE <= TCP_LOCK_SURE
    tcp_output (ns);
    mutex_unlock (&ns->ip->lock);
#elif TCP_LOCK_STYLE >= TCP_LOCK_RELAXED
    mutex_unlock (&ns->ip->lock);
    tcp_output (ns);
#endif
    mutex_unlock (&ns->lock);
	return ns;
}
Beispiel #10
0
/**
 * Called by tcp_input() when a segment arrives for a listening
 * connection (from tcp_input()).
 *
 * @param pcb the tcp_pcb_listen for which a segment arrived
 * @return ERR_OK if the segment was processed
 *         another err_t on error
 *
 * @note the return value is not (yet?) used in tcp_input()
 * @note the segment which arrived is saved in global variables, therefore only the pcb
 *       involved is passed as a parameter to this function
 */
static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
  struct tcp_pcb *npcb;
  u32_t optdata;

  /* In the LISTEN state, we check for incoming SYN segments,
     creates a new PCB, and responds with a SYN|ACK. */
  if (flags & TCP_ACK) {
    /* For incoming segments with the ACK flag set, respond with a
       RST. */
    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
    tcp_rst(ackno + 1, seqno + tcplen,
      &(iphdr->dest), &(iphdr->src),
      tcphdr->dest, tcphdr->src);
  } else if (flags & TCP_SYN) {
    LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
#if TCP_LISTEN_BACKLOG
    if (pcb->accepts_pending >= pcb->backlog) {
      return ERR_ABRT;
    }
#endif /* TCP_LISTEN_BACKLOG */
    npcb = tcp_alloc(pcb->prio);
    /* If a new PCB could not be created (probably due to lack of memory),
       we don't do anything, but rely on the sender will retransmit the
       SYN at a time when we have more memory available. */
    if (npcb == NULL) {
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
      TCP_STATS_INC(tcp.memerr);
      return ERR_MEM;
    }
#if TCP_LISTEN_BACKLOG
    pcb->accepts_pending++;
#endif /* TCP_LISTEN_BACKLOG */
    /* Set up the new PCB. */
    ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
    npcb->local_port = pcb->local_port;
    ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
    npcb->remote_port = tcphdr->src;
    npcb->state = SYN_RCVD;
    npcb->rcv_nxt = seqno + 1;
    npcb->snd_wnd = tcphdr->wnd;
    npcb->ssthresh = npcb->snd_wnd;
    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
    npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API
    npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
    /* inherit socket options */
    npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
    /* Register the new PCB so that we can begin receiving segments
       for it. */
    TCP_REG(&tcp_active_pcbs, npcb);

    /* Parse any options in the SYN. */
    tcp_parseopt(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS
    npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
#endif /* TCP_CALCULATE_EFF_SEND_MSS */

    snmp_inc_tcppassiveopens();

    /* Build an MSS option. */
    optdata = TCP_BUILD_MSS_OPTION();
    /* Send a SYN|ACK together with the MSS option. */
    tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
    return tcp_output(npcb);
  }
  return ERR_OK;
}
Beispiel #11
0
tcp_socket_t *
tcp_accept (tcp_socket_t *s)
{
	tcp_socket_t *ns;
	buf_t *p;
	ip_hdr_t *iph;
	tcp_hdr_t *h;
	unsigned long optdata;
again:
	mutex_lock (&s->lock);
	for (;;) {
		if (s->state != LISTEN) {
			mutex_unlock (&s->lock);
			tcp_debug ("tcp_accept: called in invalid state\n");
			return 0;
		}
		if (! tcp_queue_is_empty (s)) {
			p = tcp_queue_get (s);
			break;
		}
		mutex_wait (&s->lock);
	}
	mutex_unlock (&s->lock);

	/* Create a new PCB, and respond with a SYN|ACK.
	 * If a new PCB could not be created (probably due to lack of memory),
	 * we don't do anything, but rely on the sender will retransmit
	 * the SYN at a time when we have more memory available. */
	mutex_lock (&s->ip->lock);
	ns = tcp_alloc (s->ip);
	if (ns == 0) {
		tcp_debug ("tcp_accept: could not allocate PCB\n");
		++s->ip->tcp_in_discards;
		mutex_unlock (&s->ip->lock);
		buf_free (p);
		goto again;
	}
	h = (tcp_hdr_t*) p->payload;
	iph = ((ip_hdr_t*) p->payload) - 1;

	/* Set up the new PCB. */
	memcpy (ns->local_ip, iph->dest, 4);
	ns->local_port = s->local_port;
	memcpy (ns->remote_ip, iph->src, 4);
	ns->remote_port = h->src;
	ns->state = SYN_RCVD;
	ns->rcv_nxt = s->ip->tcp_input_seqno + 1;
	ns->snd_wnd = h->wnd;
	ns->ssthresh = ns->snd_wnd;
	ns->snd_wl1 = s->ip->tcp_input_seqno;
	ns->ip = s->ip;

	/* Register the new PCB so that we can begin receiving
	 * segments for it. */
	tcp_list_add (&s->ip->tcp_sockets, ns);

	/* Parse any options in the SYN. */
	tcp_parseopt (ns, h);

	/* Build an MSS option. */
	optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) |
		(((unsigned long)ns->mss / 256) << 8) | (ns->mss & 255));
	buf_free (p);

	/* Send a SYN|ACK together with the MSS option. */
	tcp_enqueue (ns, 0, 0, TCP_SYN | TCP_ACK, (unsigned char*) &optdata, 4);
	tcp_output (ns);
	mutex_unlock (&s->ip->lock);
	return ns;
}
Beispiel #12
0
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
  int err;

  /* Only PF_INET, PF_INET6 or PF_PACKET domains supported */

  if (
#if defined(CONFIG_NET_IPv6)
      domain != PF_INET6
#else
      domain != PF_INET
#endif
#if defined(CONFIG_NET_PKT)
      && domain != PF_PACKET
#endif
     )
    {
      err = EAFNOSUPPORT;
      goto errout;
    }

  /* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */

  if (
#if defined(CONFIG_NET_TCP)
        (type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) ||
#endif
#if defined(CONFIG_NET_UDP)
        (type == SOCK_DGRAM  && protocol != 0 && protocol != IPPROTO_UDP) ||
#endif
        (
#if defined(CONFIG_NET_TCP)
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_PKT)
         type != SOCK_STREAM &&
#else
         type != SOCK_STREAM
#endif
#endif
#if defined(CONFIG_NET_UDP)
#if defined(CONFIG_NET_PKT)
         type != SOCK_DGRAM &&
#else
         type != SOCK_DGRAM
#endif
#endif
#if defined(CONFIG_NET_PKT)
         type != SOCK_RAW
#endif
        )
     )
    {
      err = EPROTONOSUPPORT;
      goto errout;
    }

  /* Everything looks good.  Initialize the socket structure */
  /* Save the protocol type */

  psock->s_type = type;
  psock->s_conn = NULL;
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
  psock->s_sndcb = NULL;
#endif

  /* Allocate the appropriate connection structure.  This reserves the
   * the connection structure is is unallocated at this point.  It will
   * not actually be initialized until the socket is connected.
   */

  err = ENOMEM; /* Assume failure to allocate connection instance */
  switch (type)
    {
#ifdef CONFIG_NET_PKT
      case SOCK_RAW:
        {
          /* Allocate the packet socket connection structure and save
           * in the new socket instance.
           */

          FAR struct pkt_conn_s *conn = pkt_alloc();
          if (!conn)
            {
              /* Failed to reserve a connection structure */

              goto errout;
            }

          /* Set the reference count on the connection structure.  This
           * reference count will be increment only if the socket is
           * dup'ed
           */

          DEBUGASSERT(conn->crefs == 0);
          psock->s_conn = conn;
          conn->crefs   = 1;
        }
        break;
#endif

#ifdef CONFIG_NET_TCP
      case SOCK_STREAM:
        {
          /* Allocate the TCP connection structure and save in the new
           * socket instance.
           */

          FAR struct tcp_conn_s *conn = tcp_alloc();
          if (!conn)
            {
              /* Failed to reserve a connection structure */

              goto errout; /* With err == ENFILE or ENOMEM */
            }

          /* Set the reference count on the connection structure.  This
           * reference count will be increment only if the socket is
           * dup'ed
           */

          DEBUGASSERT(conn->crefs == 0);
          psock->s_conn = conn;
          conn->crefs   = 1;
        }
        break;
#endif

#ifdef CONFIG_NET_UDP
      case SOCK_DGRAM:
        {
          /* Allocate the UDP connection structure and save in the new
           * socket instance.
           */

          FAR struct udp_conn_s *conn = udp_alloc();
          if (!conn)
            {
              /* Failed to reserve a connection structure */

              goto errout; /* With err == ENFILE or ENOMEM */
            }

          /* Set the reference count on the connection structure.  This
           * reference count will be increment only if the socket is
           * dup'ed
           */

          DEBUGASSERT(conn->crefs == 0);
          psock->s_conn = conn;
          conn->crefs   = 1;
        }
        break;
#endif

      default:
        break;
    }

  return OK;

errout:
  set_errno(err);
  return ERROR;
}
Beispiel #13
0
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
                                        FAR struct tcp_hdr_s *tcp)
{
  FAR struct tcp_conn_s *conn;
  uint8_t domain;
  int ret;

  /* Get the appropriate IP domain */

#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv4)
  bool ipv6 = IFF_IS_IPv6(dev->d_flags);
  domain = ipv6 ? PF_INET6 : PF_INET;
#elif defined(CONFIG_NET_IPv4)
  domain = PF_INET;
#else /* defined(CONFIG_NET_IPv6) */
  domain = PF_INET6;
#endif

  /* Allocate the connection structure */

  conn = tcp_alloc(domain);
  if (conn)
    {
      /* Set up the local address (laddr) and the remote address (raddr)
       * that describes the TCP connection.
       */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
      if (ipv6)
#endif
        {
          FAR struct ipv6_hdr_s *ip = IPv6BUF;

          /* Set the IPv6 specific MSS and the IPv6 locally bound address */

          conn->mss = TCP_IPv6_INITIAL_MSS(dev);
          net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr);
#ifdef CONFIG_NETDEV_MULTINIC
          net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr);

          /* We now have to filter all outgoing transfers so that they use
           * only the MSS of this device.
           */

          DEBUGASSERT(conn->dev == NULL || conn->dev == dev);
          conn->dev = dev;
#endif

          /* Find the device that can receive packets on the network
           * associated with this local address.
           */

          ret = tcp_remote_ipv6_device(conn);
        }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
      else
#endif
        {
          FAR struct ipv4_hdr_s *ip = IPv4BUF;

          /* Set the IPv6 specific MSS and the IPv4 bound remote address. */

          conn->mss = TCP_IPv4_INITIAL_MSS(dev);
          net_ipv4addr_copy(conn->u.ipv4.raddr,
                            net_ip4addr_conv32(ip->srcipaddr));

#ifdef CONFIG_NETDEV_MULTINIC
          /* Set the local address as well */

          net_ipv4addr_copy(conn->u.ipv4.laddr,
                            net_ip4addr_conv32(ip->destipaddr));

          /* We now have to filter all outgoing transfers so that they use
           * only the MSS of this device.
           */

          DEBUGASSERT(conn->dev == NULL || conn->dev == dev);
          conn->dev = dev;
#endif

          /* Find the device that can receive packets on the network
           * associated with this local address.
           */

          ret = tcp_remote_ipv4_device(conn);
        }
#endif /* CONFIG_NET_IPv4 */

      /* Verify that a network device that can provide packets to this
       * local address was found.
       */

      if (ret < 0)
        {
          /* If no device is found, then the address is not reachable.
           * That should be impossible in this context and we should
           * probably really just assert here.
           */

          nerr("ERROR: Failed to find network device: %d\n", ret);
          tcp_free(conn);
          return NULL;
        }

      /* Fill in the necessary fields for the new connection. */

      conn->rto           = TCP_RTO;
      conn->timer         = TCP_RTO;
      conn->sa            = 0;
      conn->sv            = 4;
      conn->nrtx          = 0;
      conn->lport         = tcp->destport;
      conn->rport         = tcp->srcport;
      conn->tcpstateflags = TCP_SYN_RCVD;

      tcp_initsequence(conn->sndseq);
      conn->unacked       = 1;
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
      conn->expired       = 0;
      conn->isn           = 0;
      conn->sent          = 0;
      conn->sndseq_max    = 0;
#endif

      /* rcvseq should be the seqno from the incoming packet + 1. */

      memcpy(conn->rcvseq, tcp->seqno, 4);

#ifdef CONFIG_NET_TCP_READAHEAD
      /* Initialize the list of TCP read-ahead buffers */

      IOB_QINIT(&conn->readahead);
#endif

#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
      /* Initialize the write buffer lists */

      sq_init(&conn->write_q);
      sq_init(&conn->unacked_q);
#endif

      /* And, finally, put the connection structure into the active list.
       * Interrupts should already be disabled in this context.
       */

      dq_addlast(&conn->node, &g_active_tcp_connections);
    }

  return conn;
}