예제 #1
0
파일: ex-cxx.cpp 프로젝트: ares89/vlc
int main(void)
{
    int sd = -1;
    gnutls_global_init();

    try
    {

        /* Allow connections to servers that have OpenPGP keys as well.
         */
        gnutls::client_session session;

        /* X509 stuff */
        gnutls::certificate_credentials credentials;


        /* sets the trusted cas file
         */
        credentials.set_x509_trust_file(CAFILE, GNUTLS_X509_FMT_PEM);
        /* put the x509 credentials to the current session
         */
        session.set_credentials(credentials);

        /* Use default priorities */
        session.set_priority ("NORMAL", NULL);

        /* connect to the peer
         */
        sd = tcp_connect();
        session.set_transport_ptr((gnutls_transport_ptr_t) sd);

        /* Perform the TLS handshake
         */
        int ret = session.handshake();
        if (ret < 0)
        {
            throw std::runtime_error("Handshake failed");
        }
        else
        {
            std::cout << "- Handshake was completed" << std::endl;
        }

        session.send(MSG, strlen(MSG));
        char buffer[MAX_BUF + 1];
        ret = session.recv(buffer, MAX_BUF);
        if (ret == 0)
        {
            throw std::runtime_error("Peer has closed the TLS connection");
        }
        else if (ret < 0)
        {
            throw std::runtime_error(gnutls_strerror(ret));
        }

        std::cout << "- Received " << ret << " bytes:" << std::endl;
        std::cout.write(buffer, ret);
        std::cout << std::endl;

        session.bye(GNUTLS_SHUT_RDWR);
    }
    catch (std::exception &ex)
    {
        std::cerr << "Exception caught: " << ex.what() << std::endl;
    }

    if (sd != -1)
        tcp_close(sd);

    gnutls_global_deinit();

    return 0;
}
예제 #2
0
파일: tcp_input.c 프로젝트: 16aug/nvmeqemu
/*
 * TCP input routine, follows pages 65-76 of the
 * protocol specification dated September, 1981 very closely.
 */
void
tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
{
  	struct ip save_ip, *ip;
	register struct tcpiphdr *ti;
	caddr_t optp = NULL;
	int optlen = 0;
	int len, tlen, off;
        register struct tcpcb *tp = NULL;
	register int tiflags;
        struct socket *so = NULL;
	int todrop, acked, ourfinisacked, needoutput = 0;
	int iss = 0;
	u_long tiwin;
	int ret;
    struct ex_list *ex_ptr;
    Slirp *slirp;

	DEBUG_CALL("tcp_input");
	DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
		    (long )m, iphlen, (long )inso ));

	/*
	 * If called with m == 0, then we're continuing the connect
	 */
	if (m == NULL) {
		so = inso;
		slirp = so->slirp;

		/* Re-set a few variables */
		tp = sototcpcb(so);
		m = so->so_m;
                so->so_m = NULL;
		ti = so->so_ti;
		tiwin = ti->ti_win;
		tiflags = ti->ti_flags;

		goto cont_conn;
	}
	slirp = m->slirp;

	/*
	 * Get IP and TCP header together in first mbuf.
	 * Note: IP leaves IP header in first mbuf.
	 */
	ti = mtod(m, struct tcpiphdr *);
	if (iphlen > sizeof(struct ip )) {
	  ip_stripoptions(m, (struct mbuf *)0);
	  iphlen=sizeof(struct ip );
	}
	/* XXX Check if too short */


	/*
	 * Save a copy of the IP header in case we want restore it
	 * for sending an ICMP error message in response.
	 */
	ip=mtod(m, struct ip *);
	save_ip = *ip;
	save_ip.ip_len+= iphlen;

	/*
	 * Checksum extended TCP header and data.
	 */
	tlen = ((struct ip *)ti)->ip_len;
        tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
        memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
	ti->ti_x1 = 0;
	ti->ti_len = htons((uint16_t)tlen);
	len = sizeof(struct ip ) + tlen;
	if(cksum(m, len)) {
	  goto drop;
	}

	/*
	 * Check that TCP offset makes sense,
	 * pull out TCP options and adjust length.		XXX
	 */
	off = ti->ti_off << 2;
	if (off < sizeof (struct tcphdr) || off > tlen) {
	  goto drop;
	}
	tlen -= off;
	ti->ti_len = tlen;
	if (off > sizeof (struct tcphdr)) {
	  optlen = off - sizeof (struct tcphdr);
	  optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
	}
	tiflags = ti->ti_flags;

	/*
	 * Convert TCP protocol specific fields to host format.
	 */
	NTOHL(ti->ti_seq);
	NTOHL(ti->ti_ack);
	NTOHS(ti->ti_win);
	NTOHS(ti->ti_urp);

	/*
	 * Drop TCP, IP headers and TCP options.
	 */
	m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
	m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);

    if (slirp->restricted) {
        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
            if (ex_ptr->ex_fport == ti->ti_dport &&
                ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                break;
            }
        }
        if (!ex_ptr)
            goto drop;
    }
	/*
	 * Locate pcb for segment.
	 */
findso:
	so = slirp->tcp_last_so;
	if (so->so_fport != ti->ti_dport ||
	    so->so_lport != ti->ti_sport ||
	    so->so_laddr.s_addr != ti->ti_src.s_addr ||
	    so->so_faddr.s_addr != ti->ti_dst.s_addr) {
		so = solookup(&slirp->tcb, ti->ti_src, ti->ti_sport,
			       ti->ti_dst, ti->ti_dport);
		if (so)
			slirp->tcp_last_so = so;
	}

	/*
	 * If the state is CLOSED (i.e., TCB does not exist) then
	 * all data in the incoming segment is discarded.
	 * If the TCB exists but is in CLOSED state, it is embryonic,
	 * but should either do a listen or a connect soon.
	 *
	 * state == CLOSED means we've done socreate() but haven't
	 * attached it to a protocol yet...
	 *
	 * XXX If a TCB does not exist, and the TH_SYN flag is
	 * the only flag set, then create a session, mark it
	 * as if it was LISTENING, and continue...
	 */
        if (so == NULL) {
	  if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
	    goto dropwithreset;

	  if ((so = socreate(slirp)) == NULL)
	    goto dropwithreset;
	  if (tcp_attach(so) < 0) {
	    free(so); /* Not sofree (if it failed, it's not insqued) */
	    goto dropwithreset;
	  }

	  sbreserve(&so->so_snd, TCP_SNDSPACE);
	  sbreserve(&so->so_rcv, TCP_RCVSPACE);

	  so->so_laddr = ti->ti_src;
	  so->so_lport = ti->ti_sport;
	  so->so_faddr = ti->ti_dst;
	  so->so_fport = ti->ti_dport;

	  if ((so->so_iptos = tcp_tos(so)) == 0)
	    so->so_iptos = ((struct ip *)ti)->ip_tos;

	  tp = sototcpcb(so);
	  tp->t_state = TCPS_LISTEN;
	}

        /*
         * If this is a still-connecting socket, this probably
         * a retransmit of the SYN.  Whether it's a retransmit SYN
	 * or something else, we nuke it.
         */
        if (so->so_state & SS_ISFCONNECTING)
                goto drop;

	tp = sototcpcb(so);

	/* XXX Should never fail */
        if (tp == NULL)
		goto dropwithreset;
	if (tp->t_state == TCPS_CLOSED)
		goto drop;

	tiwin = ti->ti_win;

	/*
	 * Segment received on connection.
	 * Reset idle time and keep-alive timer.
	 */
	tp->t_idle = 0;
	if (SO_OPTIONS)
	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
	else
	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;

	/*
	 * Process options if not in LISTEN state,
	 * else do it below (after getting remote address).
	 */
	if (optp && tp->t_state != TCPS_LISTEN)
		tcp_dooptions(tp, (u_char *)optp, optlen, ti);

	/*
	 * Header prediction: check for the two common cases
	 * of a uni-directional data xfer.  If the packet has
	 * no control flags, is in-sequence, the window didn't
	 * change and we're not retransmitting, it's a
	 * candidate.  If the length is zero and the ack moved
	 * forward, we're the sender side of the xfer.  Just
	 * free the data acked & wake any higher level process
	 * that was blocked waiting for space.  If the length
	 * is non-zero and the ack didn't move, we're the
	 * receiver side.  If we're getting packets in-order
	 * (the reassembly queue is empty), add the data to
	 * the socket buffer and note that we need a delayed ack.
	 *
	 * XXX Some of these tests are not needed
	 * eg: the tiwin == tp->snd_wnd prevents many more
	 * predictions.. with no *real* advantage..
	 */
	if (tp->t_state == TCPS_ESTABLISHED &&
	    (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
	    ti->ti_seq == tp->rcv_nxt &&
	    tiwin && tiwin == tp->snd_wnd &&
	    tp->snd_nxt == tp->snd_max) {
		if (ti->ti_len == 0) {
			if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
			    SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
			    tp->snd_cwnd >= tp->snd_wnd) {
				/*
				 * this is a pure ack for outstanding data.
				 */
				if (tp->t_rtt &&
				    SEQ_GT(ti->ti_ack, tp->t_rtseq))
					tcp_xmit_timer(tp, tp->t_rtt);
				acked = ti->ti_ack - tp->snd_una;
				sbdrop(&so->so_snd, acked);
				tp->snd_una = ti->ti_ack;
				m_freem(m);

				/*
				 * If all outstanding data are acked, stop
				 * retransmit timer, otherwise restart timer
				 * using current (possibly backed-off) value.
				 * If process is waiting for space,
				 * wakeup/selwakeup/signal.  If data
				 * are ready to send, let tcp_output
				 * decide between more output or persist.
				 */
				if (tp->snd_una == tp->snd_max)
					tp->t_timer[TCPT_REXMT] = 0;
				else if (tp->t_timer[TCPT_PERSIST] == 0)
					tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;

				/*
				 * This is called because sowwakeup might have
				 * put data into so_snd.  Since we don't so sowwakeup,
				 * we don't need this.. XXX???
				 */
				if (so->so_snd.sb_cc)
					(void) tcp_output(tp);

				return;
			}
		} else if (ti->ti_ack == tp->snd_una &&
		    tcpfrag_list_empty(tp) &&
		    ti->ti_len <= sbspace(&so->so_rcv)) {
			/*
			 * this is a pure, in-sequence data packet
			 * with nothing on the reassembly queue and
			 * we have enough buffer space to take it.
			 */
			tp->rcv_nxt += ti->ti_len;
			/*
			 * Add data to socket buffer.
			 */
			if (so->so_emu) {
				if (tcp_emu(so,m)) sbappend(so, m);
			} else
				sbappend(so, m);

			/*
			 * If this is a short packet, then ACK now - with Nagel
			 *	congestion avoidance sender won't send more until
			 *	he gets an ACK.
			 *
			 * It is better to not delay acks at all to maximize
			 * TCP throughput.  See RFC 2581.
			 */
			tp->t_flags |= TF_ACKNOW;
			tcp_output(tp);
			return;
		}
	} /* header prediction */
	/*
	 * Calculate amount of space in receive window,
	 * and then do TCP input processing.
	 * Receive window is amount of space in rcv queue,
	 * but not less than advertised window.
	 */
	{ int win;
          win = sbspace(&so->so_rcv);
	  if (win < 0)
	    win = 0;
	  tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
	}

	switch (tp->t_state) {

	/*
	 * If the state is LISTEN then ignore segment if it contains an RST.
	 * If the segment contains an ACK then it is bad and send a RST.
	 * If it does not contain a SYN then it is not interesting; drop it.
	 * Don't bother responding if the destination was a broadcast.
	 * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
	 * tp->iss, and send a segment:
	 *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
	 * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
	 * Fill in remote peer address fields if not previously specified.
	 * Enter SYN_RECEIVED state, and process any other fields of this
	 * segment in this state.
	 */
	case TCPS_LISTEN: {

	  if (tiflags & TH_RST)
	    goto drop;
	  if (tiflags & TH_ACK)
	    goto dropwithreset;
	  if ((tiflags & TH_SYN) == 0)
	    goto drop;

	  /*
	   * This has way too many gotos...
	   * But a bit of spaghetti code never hurt anybody :)
	   */

	  /*
	   * If this is destined for the control address, then flag to
	   * tcp_ctl once connected, otherwise connect
	   */
	  if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
	      slirp->vnetwork_addr.s_addr) {
	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
		/* May be an add exec */
		for (ex_ptr = slirp->exec_list; ex_ptr;
		     ex_ptr = ex_ptr->ex_next) {
		  if(ex_ptr->ex_fport == so->so_fport &&
		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
		    so->so_state |= SS_CTL;
		    break;
		  }
		}
		if (so->so_state & SS_CTL) {
		    goto cont_input;
		}
	    }
	    /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
	  }

	  if (so->so_emu & EMU_NOCONNECT) {
	    so->so_emu &= ~EMU_NOCONNECT;
	    goto cont_input;
	  }

	  if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
	    u_char code=ICMP_UNREACH_NET;
	    DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
			errno,strerror(errno)));
	    if(errno == ECONNREFUSED) {
	      /* ACK the SYN, send RST to refuse the connection */
	      tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
			  TH_RST|TH_ACK);
	    } else {
	      if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	      HTONL(ti->ti_seq);             /* restore tcp header */
	      HTONL(ti->ti_ack);
	      HTONS(ti->ti_win);
	      HTONS(ti->ti_urp);
	      m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
	      m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
	      *ip=save_ip;
	      icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
	    }
            tcp_close(tp);
	    m_free(m);
	  } else {
	    /*
	     * Haven't connected yet, save the current mbuf
	     * and ti, and return
	     * XXX Some OS's don't tell us whether the connect()
	     * succeeded or not.  So we must time it out.
	     */
	    so->so_m = m;
	    so->so_ti = ti;
	    tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
	    tp->t_state = TCPS_SYN_RECEIVED;
	  }
	  return;

	cont_conn:
	  /* m==NULL
	   * Check if the connect succeeded
	   */
	  if (so->so_state & SS_NOFDREF) {
	    tp = tcp_close(tp);
	    goto dropwithreset;
	  }
	cont_input:
	  tcp_template(tp);

	  if (optp)
	    tcp_dooptions(tp, (u_char *)optp, optlen, ti);

	  if (iss)
	    tp->iss = iss;
	  else
	    tp->iss = slirp->tcp_iss;
	  slirp->tcp_iss += TCP_ISSINCR/2;
	  tp->irs = ti->ti_seq;
	  tcp_sendseqinit(tp);
	  tcp_rcvseqinit(tp);
	  tp->t_flags |= TF_ACKNOW;
	  tp->t_state = TCPS_SYN_RECEIVED;
	  tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
	  goto trimthenstep6;
	} /* case TCPS_LISTEN */

	/*
	 * If the state is SYN_SENT:
	 *	if seg contains an ACK, but not for our SYN, drop the input.
	 *	if seg contains a RST, then drop the connection.
	 *	if seg does not contain SYN, then drop it.
	 * Otherwise this is an acceptable SYN segment
	 *	initialize tp->rcv_nxt and tp->irs
	 *	if seg contains ack then advance tp->snd_una
	 *	if SYN has been acked change to ESTABLISHED else SYN_RCVD state
	 *	arrange for segment to be acked (eventually)
	 *	continue processing rest of data/controls, beginning with URG
	 */
	case TCPS_SYN_SENT:
		if ((tiflags & TH_ACK) &&
		    (SEQ_LEQ(ti->ti_ack, tp->iss) ||
		     SEQ_GT(ti->ti_ack, tp->snd_max)))
			goto dropwithreset;

		if (tiflags & TH_RST) {
                        if (tiflags & TH_ACK) {
                                tcp_drop(tp, 0); /* XXX Check t_softerror! */
                        }
			goto drop;
		}

		if ((tiflags & TH_SYN) == 0)
			goto drop;
		if (tiflags & TH_ACK) {
			tp->snd_una = ti->ti_ack;
			if (SEQ_LT(tp->snd_nxt, tp->snd_una))
				tp->snd_nxt = tp->snd_una;
		}

		tp->t_timer[TCPT_REXMT] = 0;
		tp->irs = ti->ti_seq;
		tcp_rcvseqinit(tp);
		tp->t_flags |= TF_ACKNOW;
		if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
			soisfconnected(so);
			tp->t_state = TCPS_ESTABLISHED;

			(void) tcp_reass(tp, (struct tcpiphdr *)0,
				(struct mbuf *)0);
			/*
			 * if we didn't have to retransmit the SYN,
			 * use its rtt as our initial srtt & rtt var.
			 */
			if (tp->t_rtt)
				tcp_xmit_timer(tp, tp->t_rtt);
		} else
			tp->t_state = TCPS_SYN_RECEIVED;

trimthenstep6:
		/*
		 * Advance ti->ti_seq to correspond to first data byte.
		 * If data, trim to stay within window,
		 * dropping FIN if necessary.
		 */
		ti->ti_seq++;
		if (ti->ti_len > tp->rcv_wnd) {
			todrop = ti->ti_len - tp->rcv_wnd;
			m_adj(m, -todrop);
			ti->ti_len = tp->rcv_wnd;
			tiflags &= ~TH_FIN;
		}
		tp->snd_wl1 = ti->ti_seq - 1;
		tp->rcv_up = ti->ti_seq;
		goto step6;
	} /* switch tp->t_state */
	/*
	 * States other than LISTEN or SYN_SENT.
	 * Check that at least some bytes of segment are within
	 * receive window.  If segment begins before rcv_nxt,
	 * drop leading data (and SYN); if nothing left, just ack.
	 */
	todrop = tp->rcv_nxt - ti->ti_seq;
	if (todrop > 0) {
		if (tiflags & TH_SYN) {
			tiflags &= ~TH_SYN;
			ti->ti_seq++;
			if (ti->ti_urp > 1)
				ti->ti_urp--;
			else
				tiflags &= ~TH_URG;
			todrop--;
		}
		/*
		 * Following if statement from Stevens, vol. 2, p. 960.
		 */
		if (todrop > ti->ti_len
		    || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
			/*
			 * Any valid FIN must be to the left of the window.
			 * At this point the FIN must be a duplicate or out
			 * of sequence; drop it.
			 */
			tiflags &= ~TH_FIN;

			/*
			 * Send an ACK to resynchronize and drop any data.
			 * But keep on processing for RST or ACK.
			 */
			tp->t_flags |= TF_ACKNOW;
			todrop = ti->ti_len;
		}
		m_adj(m, todrop);
		ti->ti_seq += todrop;
		ti->ti_len -= todrop;
		if (ti->ti_urp > todrop)
			ti->ti_urp -= todrop;
		else {
			tiflags &= ~TH_URG;
			ti->ti_urp = 0;
		}
	}
	/*
	 * If new data are received on a connection after the
	 * user processes are gone, then RST the other end.
	 */
	if ((so->so_state & SS_NOFDREF) &&
	    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
		tp = tcp_close(tp);
		goto dropwithreset;
	}

	/*
	 * If segment ends after window, drop trailing data
	 * (and PUSH and FIN); if nothing left, just ACK.
	 */
	todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
	if (todrop > 0) {
		if (todrop >= ti->ti_len) {
			/*
			 * If a new connection request is received
			 * while in TIME_WAIT, drop the old connection
			 * and start over if the sequence numbers
			 * are above the previous ones.
			 */
			if (tiflags & TH_SYN &&
			    tp->t_state == TCPS_TIME_WAIT &&
			    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
				iss = tp->rcv_nxt + TCP_ISSINCR;
				tp = tcp_close(tp);
				goto findso;
			}
			/*
			 * If window is closed can only take segments at
			 * window edge, and have to drop data and PUSH from
			 * incoming segments.  Continue processing, but
			 * remember to ack.  Otherwise, drop segment
			 * and ack.
			 */
			if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
				tp->t_flags |= TF_ACKNOW;
			} else {
				goto dropafterack;
			}
		}
		m_adj(m, -todrop);
		ti->ti_len -= todrop;
		tiflags &= ~(TH_PUSH|TH_FIN);
	}

	/*
	 * If the RST bit is set examine the state:
	 *    SYN_RECEIVED STATE:
	 *	If passive open, return to LISTEN state.
	 *	If active open, inform user that connection was refused.
	 *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
	 *	Inform user that connection was reset, and close tcb.
	 *    CLOSING, LAST_ACK, TIME_WAIT STATES
	 *	Close the tcb.
	 */
	if (tiflags&TH_RST) switch (tp->t_state) {

	case TCPS_SYN_RECEIVED:
	case TCPS_ESTABLISHED:
	case TCPS_FIN_WAIT_1:
	case TCPS_FIN_WAIT_2:
	case TCPS_CLOSE_WAIT:
		tp->t_state = TCPS_CLOSED;
                tcp_close(tp);
		goto drop;

	case TCPS_CLOSING:
	case TCPS_LAST_ACK:
	case TCPS_TIME_WAIT:
                tcp_close(tp);
		goto drop;
	}

	/*
	 * If a SYN is in the window, then this is an
	 * error and we send an RST and drop the connection.
	 */
	if (tiflags & TH_SYN) {
		tp = tcp_drop(tp,0);
		goto dropwithreset;
	}

	/*
	 * If the ACK bit is off we drop the segment and return.
	 */
	if ((tiflags & TH_ACK) == 0) goto drop;

	/*
	 * Ack processing.
	 */
	switch (tp->t_state) {
	/*
	 * In SYN_RECEIVED state if the ack ACKs our SYN then enter
	 * ESTABLISHED state and continue processing, otherwise
	 * send an RST.  una<=ack<=max
	 */
	case TCPS_SYN_RECEIVED:

		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
		    SEQ_GT(ti->ti_ack, tp->snd_max))
			goto dropwithreset;
		tp->t_state = TCPS_ESTABLISHED;
		/*
		 * The sent SYN is ack'ed with our sequence number +1
		 * The first data byte already in the buffer will get
		 * lost if no correction is made.  This is only needed for
		 * SS_CTL since the buffer is empty otherwise.
		 * tp->snd_una++; or:
		 */
		tp->snd_una=ti->ti_ack;
		if (so->so_state & SS_CTL) {
		  /* So tcp_ctl reports the right state */
		  ret = tcp_ctl(so);
		  if (ret == 1) {
		    soisfconnected(so);
		    so->so_state &= ~SS_CTL;   /* success XXX */
		  } else if (ret == 2) {
		    so->so_state &= SS_PERSISTENT_MASK;
		    so->so_state |= SS_NOFDREF; /* CTL_CMD */
		  } else {
		    needoutput = 1;
		    tp->t_state = TCPS_FIN_WAIT_1;
		  }
		} else {
		  soisfconnected(so);
		}

		(void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
		tp->snd_wl1 = ti->ti_seq - 1;
		/* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
		goto synrx_to_est;
		/* fall into ... */

	/*
	 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
	 * ACKs.  If the ack is in the range
	 *	tp->snd_una < ti->ti_ack <= tp->snd_max
	 * then advance tp->snd_una to ti->ti_ack and drop
	 * data from the retransmission queue.  If this ACK reflects
	 * more up to date window information we update our window information.
	 */
	case TCPS_ESTABLISHED:
	case TCPS_FIN_WAIT_1:
	case TCPS_FIN_WAIT_2:
	case TCPS_CLOSE_WAIT:
	case TCPS_CLOSING:
	case TCPS_LAST_ACK:
	case TCPS_TIME_WAIT:

		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
			  DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
				      (long )m, (long )so));
				/*
				 * If we have outstanding data (other than
				 * a window probe), this is a completely
				 * duplicate ack (ie, window info didn't
				 * change), the ack is the biggest we've
				 * seen and we've seen exactly our rexmt
				 * threshold of them, assume a packet
				 * has been dropped and retransmit it.
				 * Kludge snd_nxt & the congestion
				 * window so we send only this one
				 * packet.
				 *
				 * We know we're losing at the current
				 * window size so do congestion avoidance
				 * (set ssthresh to half the current window
				 * and pull our congestion window back to
				 * the new ssthresh).
				 *
				 * Dup acks mean that packets have left the
				 * network (they're now cached at the receiver)
				 * so bump cwnd by the amount in the receiver
				 * to keep a constant cwnd packets in the
				 * network.
				 */
				if (tp->t_timer[TCPT_REXMT] == 0 ||
				    ti->ti_ack != tp->snd_una)
					tp->t_dupacks = 0;
				else if (++tp->t_dupacks == TCPREXMTTHRESH) {
					tcp_seq onxt = tp->snd_nxt;
					u_int win =
					    min(tp->snd_wnd, tp->snd_cwnd) / 2 /
						tp->t_maxseg;

					if (win < 2)
						win = 2;
					tp->snd_ssthresh = win * tp->t_maxseg;
					tp->t_timer[TCPT_REXMT] = 0;
					tp->t_rtt = 0;
					tp->snd_nxt = ti->ti_ack;
					tp->snd_cwnd = tp->t_maxseg;
					(void) tcp_output(tp);
					tp->snd_cwnd = tp->snd_ssthresh +
					       tp->t_maxseg * tp->t_dupacks;
					if (SEQ_GT(onxt, tp->snd_nxt))
						tp->snd_nxt = onxt;
					goto drop;
				} else if (tp->t_dupacks > TCPREXMTTHRESH) {
					tp->snd_cwnd += tp->t_maxseg;
					(void) tcp_output(tp);
					goto drop;
				}
			} else
				tp->t_dupacks = 0;
			break;
		}
	synrx_to_est:
		/*
		 * If the congestion window was inflated to account
		 * for the other side's cached packets, retract it.
		 */
		if (tp->t_dupacks > TCPREXMTTHRESH &&
		    tp->snd_cwnd > tp->snd_ssthresh)
			tp->snd_cwnd = tp->snd_ssthresh;
		tp->t_dupacks = 0;
		if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
			goto dropafterack;
		}
		acked = ti->ti_ack - tp->snd_una;

		/*
		 * If transmit timer is running and timed sequence
		 * number was acked, update smoothed round trip time.
		 * Since we now have an rtt measurement, cancel the
		 * timer backoff (cf., Phil Karn's retransmit alg.).
		 * Recompute the initial retransmit timer.
		 */
		if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
			tcp_xmit_timer(tp,tp->t_rtt);

		/*
		 * If all outstanding data is acked, stop retransmit
		 * timer and remember to restart (more output or persist).
		 * If there is more data to be acked, restart retransmit
		 * timer, using current (possibly backed-off) value.
		 */
		if (ti->ti_ack == tp->snd_max) {
			tp->t_timer[TCPT_REXMT] = 0;
			needoutput = 1;
		} else if (tp->t_timer[TCPT_PERSIST] == 0)
			tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
		/*
		 * When new data is acked, open the congestion window.
		 * If the window gives us less than ssthresh packets
		 * in flight, open exponentially (maxseg per packet).
		 * Otherwise open linearly: maxseg per window
		 * (maxseg^2 / cwnd per packet).
		 */
		{
		  register u_int cw = tp->snd_cwnd;
		  register u_int incr = tp->t_maxseg;

		  if (cw > tp->snd_ssthresh)
		    incr = incr * incr / cw;
		  tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
		}
		if (acked > so->so_snd.sb_cc) {
			tp->snd_wnd -= so->so_snd.sb_cc;
			sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
			ourfinisacked = 1;
		} else {
			sbdrop(&so->so_snd, acked);
			tp->snd_wnd -= acked;
			ourfinisacked = 0;
		}
		tp->snd_una = ti->ti_ack;
		if (SEQ_LT(tp->snd_nxt, tp->snd_una))
			tp->snd_nxt = tp->snd_una;

		switch (tp->t_state) {

		/*
		 * In FIN_WAIT_1 STATE in addition to the processing
		 * for the ESTABLISHED state if our FIN is now acknowledged
		 * then enter FIN_WAIT_2.
		 */
		case TCPS_FIN_WAIT_1:
			if (ourfinisacked) {
				/*
				 * If we can't receive any more
				 * data, then closing user can proceed.
				 * Starting the timer is contrary to the
				 * specification, but if we don't get a FIN
				 * we'll hang forever.
				 */
				if (so->so_state & SS_FCANTRCVMORE) {
					tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
				}
				tp->t_state = TCPS_FIN_WAIT_2;
			}
			break;

	 	/*
		 * In CLOSING STATE in addition to the processing for
		 * the ESTABLISHED state if the ACK acknowledges our FIN
		 * then enter the TIME-WAIT state, otherwise ignore
		 * the segment.
		 */
		case TCPS_CLOSING:
			if (ourfinisacked) {
				tp->t_state = TCPS_TIME_WAIT;
				tcp_canceltimers(tp);
				tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
			}
			break;

		/*
		 * In LAST_ACK, we may still be waiting for data to drain
		 * and/or to be acked, as well as for the ack of our FIN.
		 * If our FIN is now acknowledged, delete the TCB,
		 * enter the closed state and return.
		 */
		case TCPS_LAST_ACK:
			if (ourfinisacked) {
                                tcp_close(tp);
				goto drop;
			}
			break;

		/*
		 * In TIME_WAIT state the only thing that should arrive
		 * is a retransmission of the remote FIN.  Acknowledge
		 * it and restart the finack timer.
		 */
		case TCPS_TIME_WAIT:
			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
			goto dropafterack;
		}
	} /* switch(tp->t_state) */

step6:
	/*
	 * Update window information.
	 * Don't look at window if no ACK: TAC's send garbage on first SYN.
	 */
	if ((tiflags & TH_ACK) &&
	    (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
	    (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
	    (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
		tp->snd_wnd = tiwin;
		tp->snd_wl1 = ti->ti_seq;
		tp->snd_wl2 = ti->ti_ack;
		if (tp->snd_wnd > tp->max_sndwnd)
			tp->max_sndwnd = tp->snd_wnd;
		needoutput = 1;
	}

	/*
	 * Process segments with URG.
	 */
	if ((tiflags & TH_URG) && ti->ti_urp &&
	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {
		/*
		 * This is a kludge, but if we receive and accept
		 * random urgent pointers, we'll crash in
		 * soreceive.  It's hard to imagine someone
		 * actually wanting to send this much urgent data.
		 */
		if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) {
			ti->ti_urp = 0;
			tiflags &= ~TH_URG;
			goto dodata;
		}
		/*
		 * If this segment advances the known urgent pointer,
		 * then mark the data stream.  This should not happen
		 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
		 * a FIN has been received from the remote side.
		 * In these states we ignore the URG.
		 *
		 * According to RFC961 (Assigned Protocols),
		 * the urgent pointer points to the last octet
		 * of urgent data.  We continue, however,
		 * to consider it to indicate the first octet
		 * of data past the urgent section as the original
		 * spec states (in one of two places).
		 */
		if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
			tp->rcv_up = ti->ti_seq + ti->ti_urp;
			so->so_urgc =  so->so_rcv.sb_cc +
				(tp->rcv_up - tp->rcv_nxt); /* -1; */
			tp->rcv_up = ti->ti_seq + ti->ti_urp;

		}
	} else
		/*
		 * If no out of band data is expected,
		 * pull receive urgent pointer along
		 * with the receive window.
		 */
		if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
			tp->rcv_up = tp->rcv_nxt;
dodata:

	/*
	 * Process the segment text, merging it into the TCP sequencing queue,
	 * and arranging for acknowledgment of receipt if necessary.
	 * This process logically involves adjusting tp->rcv_wnd as data
	 * is presented to the user (this happens in tcp_usrreq.c,
	 * case PRU_RCVD).  If a FIN has already been received on this
	 * connection then we just ignore the text.
	 */
	if ((ti->ti_len || (tiflags&TH_FIN)) &&
	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {
		TCP_REASS(tp, ti, m, so, tiflags);
	} else {
		m_free(m);
		tiflags &= ~TH_FIN;
	}

	/*
	 * If FIN is received ACK the FIN and let the user know
	 * that the connection is closing.
	 */
	if (tiflags & TH_FIN) {
		if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
			/*
			 * If we receive a FIN we can't send more data,
			 * set it SS_FDRAIN
                         * Shutdown the socket if there is no rx data in the
			 * buffer.
			 * soread() is called on completion of shutdown() and
			 * will got to TCPS_LAST_ACK, and use tcp_output()
			 * to send the FIN.
			 */
			sofwdrain(so);

			tp->t_flags |= TF_ACKNOW;
			tp->rcv_nxt++;
		}
		switch (tp->t_state) {

	 	/*
		 * In SYN_RECEIVED and ESTABLISHED STATES
		 * enter the CLOSE_WAIT state.
		 */
		case TCPS_SYN_RECEIVED:
		case TCPS_ESTABLISHED:
		  if(so->so_emu == EMU_CTL)        /* no shutdown on socket */
		    tp->t_state = TCPS_LAST_ACK;
		  else
		    tp->t_state = TCPS_CLOSE_WAIT;
		  break;

	 	/*
		 * If still in FIN_WAIT_1 STATE FIN has not been acked so
		 * enter the CLOSING state.
		 */
		case TCPS_FIN_WAIT_1:
			tp->t_state = TCPS_CLOSING;
			break;

	 	/*
		 * In FIN_WAIT_2 state enter the TIME_WAIT state,
		 * starting the time-wait timer, turning off the other
		 * standard timers.
		 */
		case TCPS_FIN_WAIT_2:
			tp->t_state = TCPS_TIME_WAIT;
			tcp_canceltimers(tp);
			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
			break;

		/*
		 * In TIME_WAIT state restart the 2 MSL time_wait timer.
		 */
		case TCPS_TIME_WAIT:
			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
			break;
		}
	}

	/*
	 * If this is a small packet, then ACK now - with Nagel
	 *      congestion avoidance sender won't send more until
	 *      he gets an ACK.
	 *
	 * See above.
	 */
	if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
	    ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
		tp->t_flags |= TF_ACKNOW;
	}

	/*
	 * Return any desired output.
	 */
	if (needoutput || (tp->t_flags & TF_ACKNOW)) {
		(void) tcp_output(tp);
	}
	return;

dropafterack:
	/*
	 * Generate an ACK dropping incoming segment if it occupies
	 * sequence space, where the ACK reflects our state.
	 */
	if (tiflags & TH_RST)
		goto drop;
	m_freem(m);
	tp->t_flags |= TF_ACKNOW;
	(void) tcp_output(tp);
	return;

dropwithreset:
	/* reuses m if m!=NULL, m_free() unnecessary */
	if (tiflags & TH_ACK)
		tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
	else {
		if (tiflags & TH_SYN) ti->ti_len++;
		tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
		    TH_RST|TH_ACK);
	}

	return;

drop:
	/*
	 * Drop space held by incoming segment and return.
	 */
	m_free(m);

	return;
}
예제 #3
0
void
tcp_timer_2msl(void *xtp)
{
	struct tcpcb *tp = xtp;
	struct inpcb *inp;
	CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
	int ostate;

	ostate = tp->t_state;
#endif
	/*
	 * XXXRW: Does this actually happen?
	 */
	INP_INFO_WLOCK(&V_tcbinfo);
	inp = tp->t_inpcb;
	/*
	 * XXXRW: While this assert is in fact correct, bugs in the tcpcb
	 * tear-down mean we need it as a work-around for races between
	 * timers and tcp_discardcb().
	 *
	 * KASSERT(inp != NULL, ("tcp_timer_2msl: inp == NULL"));
	 */
	if (inp == NULL) {
		tcp_timer_race++;
		INP_INFO_WUNLOCK(&V_tcbinfo);
		CURVNET_RESTORE();
		return;
	}
	INP_WLOCK(inp);
	tcp_free_sackholes(tp);
	if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_2msl) ||
	    !callout_active(&tp->t_timers->tt_2msl)) {
		INP_WUNLOCK(tp->t_inpcb);
		INP_INFO_WUNLOCK(&V_tcbinfo);
		CURVNET_RESTORE();
		return;
	}
	callout_deactivate(&tp->t_timers->tt_2msl);
	/*
	 * 2 MSL timeout in shutdown went off.  If we're closed but
	 * still waiting for peer to close and connection has been idle
	 * too long, or if 2MSL time is up from TIME_WAIT, delete connection
	 * control block.  Otherwise, check again in a bit.
	 *
	 * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, 
	 * there's no point in hanging onto FIN_WAIT_2 socket. Just close it. 
	 * Ignore fact that there were recent incoming segments.
	 */
	if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
	    tp->t_inpcb && tp->t_inpcb->inp_socket && 
	    (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
		TCPSTAT_INC(tcps_finwait2_drops);
		tp = tcp_close(tp);             
	} else {
		if (tp->t_state != TCPS_TIME_WAIT &&
		   ticks - tp->t_rcvtime <= TP_MAXIDLE(tp))
		       callout_reset_on(&tp->t_timers->tt_2msl,
			   TP_KEEPINTVL(tp), tcp_timer_2msl, tp, INP_CPU(inp));
	       else
		       tp = tcp_close(tp);
       }

#ifdef TCPDEBUG
	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
			  PRU_SLOWTIMO);
#endif
	if (tp != NULL)
		INP_WUNLOCK(inp);
	INP_INFO_WUNLOCK(&V_tcbinfo);
	CURVNET_RESTORE();
}
예제 #4
0
파일: http.c 프로젝트: Bob4ik888/WebRadio
void http_tcpapp(unsigned int idx, char *rx, unsigned int rx_len, unsigned char *tx)
{
  unsigned int tx_len;

  DEBUGOUT("HTTP: TCP app\n");

  switch(http_table[idx].status)
  {
    case HTTP_CLOSED: //new connection
      if(rx_len)
      {
        if(strncmpi(rx, "GET", 3) == 0)
        {
          rx     += 3+1;
          rx_len -= 3+1;
          http_sendfile(idx, rx, tx);
        }
        else if(strncmpi(rx, "POST", 4) == 0)
        {
          rx     += 4+1;
          rx_len -= 4+1;
          if(strncmpi(rx, "/station", 8) == 0)
          {
            http_table[idx].status = HTTP_STATION;
            rx = (char*)http_skiphd(rx, &rx_len);
          }
          else if(strncmpi(rx, "/alarm", 6) == 0)
          {
            http_table[idx].status = HTTP_ALARM;
            rx = http_skiphd(rx, &rx_len);
          }
          else if(strncmpi(rx, "/settings", 9) == 0)
          {
            http_table[idx].status = HTTP_SETTINGS;
            rx = http_skiphd(rx, &rx_len);
          }
          else
          {
            http_sendfile(idx, rx, tx);
          }
        }
        else
        {
          tx_len = sprintf((char*)tx, HTTP_400_HEADER"Error 400 Bad request\r\n\r\n");
          tcp_send(idx, tx_len, 0);
          tcp_close(idx);
        }
      }
      break;

    case HTTP_SEND:
      http_sendfile(idx, 0, tx);
      break;
  }

  //parse station, alarm or settings
  switch(http_table[idx].status)
  {
    case HTTP_STATION:
      if(rx_len)
      {
        http_station(rx, rx_len);
        http_sendfile(idx, "/station", tx);
      }
      else
      {
        tcp_send(idx, 0, 0);
      }
      break;

    case HTTP_ALARM:
      if(rx_len)
      {
        http_alarm(rx, rx_len);
        http_sendfile(idx, "/alarm", tx);
      }
      else
      {
        tcp_send(idx, 0, 0);
      }
      break;

    case HTTP_SETTINGS:
      if(rx_len)
      {
        http_settings(rx, rx_len);
        http_sendfile(idx, "/settings", tx);
      }
      else
      {
        tcp_send(idx, 0, 0);
      }
      break;
  }

  return;
}
예제 #5
0
파일: tcp.c 프로젝트: imaginegit/wifisdk
/**
 * Called every 500 ms and implements the retransmission timer and the timer that
 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
 * various timers such as the inactivity timer in each PCB.
 *
 * Automatically called from tcp_tmr().
 */
void tcp_slowtmr(void)
{
    TCP_PCB *pcb, *pcb2, *prev;
    uint16 eff_wnd;
    uint8 err= ERR_OK;

    ++tcp_ticks;

    /* Steps through all of the active PCBs. */
    prev = NULL;
    pcb = &stTcpPcb;

    if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX)
    {
        printf("SYN SENT CLOSED\n");
        pcb->state = CLOSED;
        tcp_pcb_purge(pcb);
	    tcp_close(pcb);
        return;
    }
    else if (pcb->nrtx == TCP_MAXRTX)
    {
        printf("TCP MAXRTX CLOSED\n");
        pcb->state = CLOSED;
        tcp_pcb_purge(pcb);
	    tcp_close(pcb);
        return;
    }
    else
    {
        if (pcb->persist_backoff > 0)
        {
            /* If snd_wnd is zero, use persist timer to send 1 byte probes
             * instead of using the standard retransmission mechanism. */
            pcb->persist_cnt++;
            if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1])
            {
                pcb->persist_cnt = 0;
                if (pcb->persist_backoff < sizeof(tcp_persist_backoff))
                {
                    pcb->persist_backoff++;
                }
                tcp_zero_window_probe(pcb);
            }
        }
        else
        {
            /* Increase the retransmission timer if it is running */
            if (pcb->rtime >= 0)
                ++pcb->rtime;

            if (pcb->unacked != NULL && pcb->rtime >= pcb->rto)
            {
                /* Double retransmission time-out unless we are trying to
                 * connect to somebody (i.e., we are in SYN_SENT). */
                if (pcb->state != SYN_SENT)
                {
                    pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
                }

                /* Reset the retransmission timer. */
                pcb->rtime = 0;

                /* Reduce congestion window and ssthresh. */
                eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
                pcb->ssthresh = eff_wnd >> 1;
                if (pcb->ssthresh < pcb->mss)
                {
                    pcb->ssthresh = pcb->mss * 2;
                }
                pcb->cwnd = pcb->mss;

                /* The following needs to be called AFTER cwnd is set to one
                   mss - STJ */
                tcp_rexmit_rto(pcb);
            }
        }
    }
예제 #6
0
파일: tcp_subr.c 프로젝트: 8tab/qemu
void tcp_cleanup(Slirp *slirp)
{
    while (slirp->tcb.so_next != &slirp->tcb) {
        tcp_close(sototcpcb(slirp->tcb.so_next));
    }
}
예제 #7
0
파일: client.cpp 프로젝트: flyingtime/boxee
void client_test(void* args)
{
#ifdef _WIN32
    WSADATA wsd;
    WSAStartup(0x0002, &wsd);
#endif

    SOCKET_T sockfd = 0;
    int      argc = 0;
    char**   argv = 0;

    set_args(argc, argv, *static_cast<func_args*>(args));
    tcp_connect(sockfd);
#ifdef NON_BLOCKING
    tcp_set_nonblocking(sockfd);
#endif

    SSL_METHOD* method = TLSv1_client_method();
    SSL_CTX*    ctx = SSL_CTX_new(method);

    set_certs(ctx);
    SSL* ssl = SSL_new(ctx);

    SSL_set_fd(ssl, sockfd);


#ifdef NON_BLOCKING
    NonBlockingSSL_Connect(ssl, ctx, sockfd);
#else
    // if you get an error here see note at top of README
    if (SSL_connect(ssl) != SSL_SUCCESS)   
        ClientError(ctx, ssl, sockfd, "SSL_connect failed");
#endif
    showPeer(ssl);

    const char* cipher = 0;
    int index = 0;
    char list[1024];
    strncpy(list, "cipherlist", 11);
    while ( (cipher = SSL_get_cipher_list(ssl, index++)) ) {
        strncat(list, ":", 2);
        strncat(list, cipher, strlen(cipher) + 1);
    }
    printf("%s\n", list);
    printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl));

    char msg[] = "hello yassl!";
    if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
        ClientError(ctx, ssl, sockfd, "SSL_write failed");

    char reply[1024];
    int input = SSL_read(ssl, reply, sizeof(reply));
    if (input > 0) {
        reply[input] = 0;
        printf("Server response: %s\n", reply);
    }

#ifdef TEST_RESUME
    SSL_SESSION* session   = SSL_get_session(ssl);
    SSL*         sslResume = SSL_new(ctx);
#endif

    SSL_shutdown(ssl);
    SSL_free(ssl);
    tcp_close(sockfd);

#ifdef TEST_RESUME
    tcp_connect(sockfd);
    SSL_set_fd(sslResume, sockfd);
    SSL_set_session(sslResume, session);

    if (SSL_connect(sslResume) != SSL_SUCCESS)
        ClientError(ctx, sslResume, sockfd, "SSL_resume failed");
    showPeer(sslResume);

    if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg))
        ClientError(ctx, sslResume, sockfd, "SSL_write failed");

    input = SSL_read(sslResume, reply, sizeof(reply));
    if (input > 0) {
        reply[input] = 0;
        printf("Server response: %s\n", reply);
    }

    SSL_shutdown(sslResume);
    SSL_free(sslResume);
    tcp_close(sockfd);
#endif // TEST_RESUME

    SSL_CTX_free(ctx);
    ((func_args*)args)->return_code = 0;
}
예제 #8
0
파일: rtsp.c 프로젝트: bobmittmann/thinkos
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;
}
예제 #9
0
파일: rtsp.c 프로젝트: bobmittmann/thinkos
int rtsp_line_recv(struct rtsp_client * rtsp, char * line,
		unsigned int len)
{
	struct tcp_pcb * tp = rtsp->tcp;
	int rem;
	int cnt;
	int pos;
	int lin;
	int c1;
	int c2;
	int n;

	cnt = rtsp->cnt;
	pos = rtsp->pos;
	lin = rtsp->lin;
	c1 = (pos) ? rtsp->buf[pos - 1] : '\0';

	/* receive SDP payload */
	for (;;) {
		/* search for end of line */
		while (pos < cnt) {
			c2 = rtsp->buf[pos++];
			if (c1 == '\r' && c2 == '\n') {
				char * dst = line;
				char * src = &rtsp->buf[lin];
				int i;

				n = pos - lin - 2;
				if (n > len)
					n = len;

				for (i = 0; i < n; ++i)
					dst[i] = src[i];

				/* move to the next line */
				lin = pos;
				rtsp->lin = lin;
				rtsp->pos = lin;
				return n;
			}
			c1 = c2;
		}

		/* */
		if (rtsp->resp.content_len == rtsp->resp.content_pos) {
			/* get the number of remaining characters, ignoring
			 * a possible CR at the end*/
			n = pos - lin - (c1 == '\r') ? 1 : 0;

			if (n != 0) {
				/* this is the last line and there is no CR+LF at the end of it */
				char * dst = line;
				char * src = &rtsp->buf[lin];
				int i;

				if (n > len)
					n = len;
				for (i = 0; i < n; ++i)
					dst[i] = src[i];
			}
			/* update our pointers */
			rtsp->pos = pos;
			rtsp->lin = lin;
			return n;
		}

		if (RTSP_CLIENT_BUF_LEN == cnt) {
			int i;
			int j;

			if (lin == 0) {
				ERR("buffer overflow!");
				return -1;
			}

			/* move remaining data to the beginning of the buffer */
			n = cnt - lin;
			for (i = 0, j = lin; i < n; ++i, ++j)
				rtsp->buf[i] = rtsp->buf[j];

			cnt = n;
			pos = n;
			lin = 0;
		}

		/* free space in the input buffer */
		rem = RTSP_CLIENT_BUF_LEN - cnt;
		/* read more data */
		if ((n = tcp_recv(tp, &rtsp->buf[cnt], rem)) <= 0) {
			tcp_close(tp);
			return n;
		}

		rtsp->resp.content_pos += n;
		cnt += n;
		rtsp->cnt = cnt;
	}

	return 0;
}
예제 #10
0
int main(void) {
    
    char server_buf[BUF_SIZE], client_buf[BUF_SIZE];
    char *eth, *ip1, *ip2;

    int pid, status, total, read;
    int j, v;

    ipaddr_t saddr;

    eth = getenv("ETH");
    if (!eth) {
        fprintf(stderr, "The ETH environment variable must be set!\n");
        return 1;
    }

    ip1 = getenv("IP1");
    ip2 = getenv("IP2");
    if ((!ip1)||(!ip2)) {
        fprintf(stderr, "The IP1 and IP2 environment variables must be set!\n");
        return 1;
    }
    
            /* fill buffer with ASCII pattern 012345670123... */
        for (v=0;v<BUF_SIZE;v++) {
            client_buf[v] = (v % 8) + 48;
        }

        /* Client process running in $IP1 */
        eth[0] = '1';
 
        if (tcp_socket() != 0) {
            fprintf(stderr, "Client: Opening socket failed\n");
            return 1;
        }

        
        signal(SIGALRM, alarm_handler);
        alarm(10);
        
        if (tcp_connect(inet_aton(ip2), 80) != 0) {
            fprintf(stderr, "Client: Connecting to server failed\n");
            return 1;
        }
        
        j = tcp_write(client_buf, BUF_SIZE);
        if (j < 1) {
            fprintf(stderr, "Client: Writing failed\n"); 
            return 1;
        }
        fprintf(stderr,"Client: Sent %d Kbytes\n",j);    
       
        
        if (tcp_close() != 0) {
            fprintf(stderr, "Client: Closing connection failed\n");
            return 1;
        }

        signal(SIGALRM, alarm_handler);
        alarm(3);

        while (tcp_read(client_buf, 4) > 0) {}

        alarm(0);

        return 0;
    
}
예제 #11
0
파일: rtsp.c 프로젝트: bobmittmann/thinkos
int rtsp_wait_reply(struct rtsp_client * rtsp, int tmo)
{
	struct tcp_pcb * tp = rtsp->tcp;
	char * buf = rtsp->buf;
	int n;
	int i;
	int c1;
	int c2;
	int rem;
	int cnt;
	int ln;
	int pos;

	rem = RTSP_CLIENT_BUF_LEN; /* free space in the input buffer */
	cnt = 0; /* used space in the input buffer */
	ln = 0; /* line start */
	pos = 0; /* header position */
	c1 = '\0';

	/* receive and decode RTSP headers */
	while ((n = tcp_recv(tp, &buf[cnt], rem)) > 0)  {
		rem -= n;
		i = cnt;
		cnt += n;
		for (; i < cnt; ++i) {
			c2 = buf[i];
			if (c1 == '\r' && c2 == '\n') {
				char * val;
				unsigned int hdr;

				buf[i - 1] = '\0';
#if 0
				printf("%s\n", &buf[ln]);
#endif

				if (i == ln + 1) {
					DBG("end of RTSP header");
					i++;
					rtsp->cnt = cnt;
					rtsp->pos = i;
					rtsp->lin = i;

					if (rtsp->resp.code != 200) {
						WARN("Server response code: %d", rtsp->resp.code);
						return -1;
					}

					return 0;
				}

				if ((hdr = rtsp_parse_hdr(&buf[ln], &val)) == 0) {
					WARN("invalid header field: \"%s\"", &buf[ln]);
//					return -1;
				} else {
//					DBG("header field received: %s", rtsp_hdr_name[hdr]);
					if (pos == 0) {
						if (hdr != HDR_RTSP_1_0) {
							WARN("invalid response");
							return -1;
						}
						rtsp->resp.code = atoi(val);
					} else {
						switch (hdr) {
						case HDR_CSEQ:
							if (atoi(val) != rtsp->cseq) {
								WARN("invalid CSeq");
								return -1;
							}
							break;

						case HDR_SESSION:
							rtsp->sid = strtoull(val, NULL, 16);
							break;

						case HDR_TRANSPORT:
							rtsp_decode_transport(rtsp, val);
							break;

						case HDR_CONTENT_LENGTH:
							rtsp->resp.content_len = strtoul(val, NULL, 10);
//							DBG("Content Length: %d", rtsp->content_len);
							break;
						}
					}
				}
				/* increment header counter */
				pos++;
				/* move to the next line */
				ln = i + 1;
			}
			c1 = c2;
		}

		if (ln != 0) {
			int j;

			for (i = 0, j = ln; j < cnt; ++i, ++j)
				buf[i] = buf[j];
			cnt = i;
			rem = RTSP_CLIENT_BUF_LEN - i;
			ln = 0;
		}

		if (rem <= 0) {
			ERR("buffer ovreflow!");
			return -1;
		}
	}

	tcp_close(tp);

	return -1;
}
예제 #12
0
STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
    lwip_socket_obj_t *socket = self_in;
    mp_uint_t ret;

    if (request == MP_STREAM_POLL) {
        uintptr_t flags = arg;
        ret = 0;

        if (flags & MP_STREAM_POLL_RD && socket->incoming.pbuf != NULL) {
            ret |= MP_STREAM_POLL_RD;
        }

        // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
        if (flags & MP_STREAM_POLL_WR && socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
            ret |= MP_STREAM_POLL_WR;
        }

        if (socket->state == STATE_NEW) {
            // New sockets are not connected so set HUP
            ret |= flags & MP_STREAM_POLL_HUP;
        } else if (socket->state == STATE_PEER_CLOSED) {
            // Peer-closed socket is both readable and writable: read will
            // return EOF, write - error. Without this poll will hang on a
            // socket which was closed by peer.
            ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
        } else if (socket->state == ERR_RST) {
            // Socket was reset by peer, a write will return an error
            ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP);
        } else if (socket->state < 0) {
            // Socket in some other error state, use catch-all ERR flag
            // TODO: may need to set other return flags here
            ret |= flags & MP_STREAM_POLL_ERR;
        }

    } else if (request == MP_STREAM_CLOSE) {
        bool socket_is_listener = false;

        if (socket->pcb.tcp == NULL) {
            return 0;
        }
        switch (socket->type) {
            case MOD_NETWORK_SOCK_STREAM: {
                if (socket->pcb.tcp->state == LISTEN) {
                    socket_is_listener = true;
                }
                if (tcp_close(socket->pcb.tcp) != ERR_OK) {
                    DEBUG_printf("lwip_close: had to call tcp_abort()\n");
                    tcp_abort(socket->pcb.tcp);
                }
                break;
            }
            case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break;
            //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break;
        }
        socket->pcb.tcp = NULL;
        socket->state = _ERR_BADF;
        if (socket->incoming.pbuf != NULL) {
            if (!socket_is_listener) {
                pbuf_free(socket->incoming.pbuf);
            } else {
                tcp_abort(socket->incoming.connection);
            }
            socket->incoming.pbuf = NULL;
        }
        ret = 0;

    } else {
        *errcode = MP_EINVAL;
        ret = MP_STREAM_ERROR;
    }

    return ret;
}
예제 #13
0
static
DWORD
vmdirConnAccept(
    Sockbuf_IO*         pSockbuf_IO,
    DWORD               dwPort,
    BOOLEAN             bIsLdaps
    )
{
    ber_socket_t         newsockfd = -1;
    int                  retVal = LDAP_SUCCESS;
    ber_socket_t         ip4_fd = -1;
    ber_socket_t         ip6_fd = -1;
    ber_socket_t         max_fd = -1;
    VMDIR_THREAD         threadId;
    BOOLEAN              bInLock = FALSE;
    int                  iLocalLogMask = 0;
    PVDIR_CONNECTION_CTX pConnCtx = NULL;
    fd_set               event_fd_set;
    fd_set               poll_fd_set;
    struct timeval       timeout = {0};

    // Wait for ***1st*** replication cycle to be over.
    if (gVmdirServerGlobals.serverId == 0) // instance has not been initialized
    {
        VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Connection accept thread: Have NOT yet started listening on LDAP port (%u),"
                  " waiting for the 1st replication cycle to be over.", dwPort);

        VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex);
        // wait till 1st replication cycle is over
        if (VmDirConditionWait( gVmdirGlobals.replCycleDoneCondition, gVmdirGlobals.replCycleDoneMutex ) != 0)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "Connection accept thread: VmDirConditionWait failed." );
            retVal = LDAP_OPERATIONS_ERROR;
            goto cleanup;
        }
        // also wake up the other (normal LDAP port/SSL LDAP port listner) LDAP connection accept thread,
        // waiting on 1st replication cycle to be over
        // BUGBUG Does not handle spurious wake up
        VmDirConditionSignal(gVmdirGlobals.replCycleDoneCondition);
        VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex);

        if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) // Asked to shutdown before we started accepting
        {
            goto cleanup;
        }

        VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Connection accept thread: listening on LDAP port (%u).", dwPort);
    }

    iLocalLogMask = VmDirLogGetMask();
    ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &iLocalLogMask);

    SetupLdapPort(dwPort, &ip4_fd, &ip6_fd);
    if (ip4_fd < 0 && ip6_fd < 0)
    {
        VmDirSleep(1000);
        goto cleanup;
    }

    FD_ZERO(&event_fd_set);
    if (ip4_fd >= 0)
    {
        FD_SET (ip4_fd, &event_fd_set);
        if (ip4_fd > max_fd)
        {
            max_fd = ip4_fd;
        }
    }

    if (ip6_fd >= 0)
    {
        FD_SET (ip6_fd, &event_fd_set);
        if (ip6_fd > max_fd)
        {
            max_fd = ip6_fd;
        }
    }

    retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter);
    if (retVal != 0 )
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter) returned error", __func__);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    while (TRUE)
    {
        if (VmDirdState() == VMDIRD_STATE_SHUTDOWN)
        {
            goto cleanup;
        }

        poll_fd_set = event_fd_set;
        timeout.tv_sec = 3;
        timeout.tv_usec = 0;
        retVal = select ((int)max_fd+1, &poll_fd_set, NULL, NULL, &timeout);
        if (retVal < 0 )
        {
#ifdef _WIN32
            errno = WSAGetLastError();
#endif
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: select() (port %d) call failed: %d.", __func__, dwPort, errno);
            VmDirSleep( 1000 );
            continue;
        } else if (retVal == 0)
        {
            //VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() timeout (port %d)", __func__, dwPort);
            continue;
        }

        if (ip4_fd >= 0 && FD_ISSET(ip4_fd, &poll_fd_set))
        {
            newsockfd = accept(ip4_fd, (struct sockaddr *) NULL, NULL);
        } else if (ip6_fd >= 0 && FD_ISSET(ip6_fd, &poll_fd_set))
        {
            newsockfd = accept(ip6_fd, (struct sockaddr *) NULL, NULL);
        } else
        {
            VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() returned with no data (port %d), return: %d",
                            __func__, dwPort, retVal);
            continue;
        }

        if (newsockfd < 0)
        {
#ifdef _WIN32
            errno = WSAGetLastError();
#endif
            if (errno != EAGAIN && errno != EWOULDBLOCK )
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: accept() (port %d) failed with errno: %d.",
                                 __func__, dwPort, errno );
            }
            continue;
        }

        if ( _VmDirFlowCtrlThrEnter() == TRUE )
        {
            tcp_close(newsockfd);
            newsockfd = -1;
            VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Maxmimum number of concurrent LDAP threads reached. Blocking new connection" );

            continue;
        }

        retVal = VmDirAllocateMemory(
                sizeof(VDIR_CONNECTION_CTX),
                (PVOID*)&pConnCtx);
        BAIL_ON_VMDIR_ERROR(retVal);

        pConnCtx->sockFd  = newsockfd;
        newsockfd = -1;
        pConnCtx->pSockbuf_IO = pSockbuf_IO;

        retVal = VmDirCreateThread(&threadId, TRUE, ProcessAConnection, (PVOID)pConnCtx);
        if (retVal != 0)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: VmDirCreateThread() (port) failed with errno: %d",
                             __func__, dwPort, errno );

            tcp_close(pConnCtx->sockFd);
            _VmDirFlowCtrlThrExit();
            VMDIR_SAFE_FREE_MEMORY(pConnCtx);
            continue;
        }
        else
        {
            pConnCtx = NULL; //thread take ownership on pConnCtx
            VmDirFreeVmDirThread(&threadId);
        }
    }

cleanup:

    VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex);

    if (ip4_fd >= 0)
    {
        tcp_close(ip4_fd);
    }
    if (ip6_fd >= 0)
    {
        tcp_close(ip6_fd);
    }
    if (newsockfd >= 0)
    {
        tcp_close(newsockfd);
    }
#ifndef _WIN32
    raise(SIGTERM);
#endif

    VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s: Connection accept thread: stop (port %d)", __func__, dwPort);

    return retVal;

error:
    goto cleanup;
}
예제 #14
0
static
int
BindListenOnPort(
#ifndef _WIN32
   sa_family_t   addr_type,
   size_t        addr_size,
#else
   short         addr_type,
   int           addr_size,
#endif
    void         *pServ_addr,
    ber_socket_t *pSockfd
)
{
#define LDAP_PORT_LISTEN_BACKLOG 128
   int  optname = 0;
   int  retVal = LDAP_SUCCESS;
   int  retValBind = 0;
   PSTR pszLocalErrMsg = NULL;
   int  on = 1;
#ifdef _WIN32
   DWORD sTimeout = 0;
   int  reTries = 0;
#else
   struct timeval sTimeout = {0};
#endif

   *pSockfd = -1;
   *pSockfd = socket(addr_type, SOCK_STREAM, 0);
   if (*pSockfd < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: socket() call failed with errno: %d", __func__, errno );
   }

#ifdef _WIN32
    optname = SO_EXCLUSIVEADDRUSE;
#else
    optname = SO_REUSEADDR;
#endif

   if (setsockopt(*pSockfd, SOL_SOCKET, optname, (const char *)(&on), sizeof(on)) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() call failed with errno: %d", __func__, errno );
   }

   on = 1;  // turn on TCP_NODELAY below

   if (setsockopt(*pSockfd,  IPPROTO_TCP, TCP_NODELAY, (const char *)(&on), sizeof(on) ) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() TCP_NODELAY call failed with errno: %d", __func__, errno );
   }

   if (addr_type == AF_INET6)
   {
#ifdef _WIN32
       if (setsockopt(*pSockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
           errno = WSAGetLastError();
#else
       if (setsockopt(*pSockfd, SOL_IPV6, IPV6_V6ONLY, (const char *)(&on), sizeof(on) ) < 0)
       {
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() IPV6_V6ONLY call failed with errno: %d", __func__, errno );
       }
   }

   if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0)
   {
#ifdef _WIN32
       sTimeout = gVmdirGlobals.dwLdapRecvTimeoutSec*1000;
#else
       sTimeout.tv_sec = gVmdirGlobals.dwLdapRecvTimeoutSec;
       sTimeout.tv_usec = 0;
#endif
       if (setsockopt(*pSockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &sTimeout, sizeof(sTimeout)) < 0)
       {
#ifdef _WIN32
           errno = WSAGetLastError();
#endif
           retVal = LDAP_OPERATIONS_ERROR;
           BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: setsockopt() SO_RCVTIMEO failed, errno: %d", __func__, errno );
       }
   }

   retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);

#ifdef _WIN32
   // Add retry logic per PR 1347783
   reTries = 0;
   while (retValBind != 0 && reTries < MAX_NUM_OF_BIND_PORT_RETRIES)
   {
      errno = WSAGetLastError();
      if (errno != WSAEADDRINUSE)
      {
         break;
      }
      reTries++;
      VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: bind() call failed with errno: %d, re-trying (%d)",
                                   __func__, errno, reTries);
      VmDirSleep(1000);
      retValBind = bind(*pSockfd, (struct sockaddr *) pServ_addr, addr_size);
   }
#endif

   if (retValBind != 0)
   {
      retVal = LDAP_OPERATIONS_ERROR;
      //need to free socket ...
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: bind() call failed with errno: %d", __func__, errno );
   }

   if (listen(*pSockfd, LDAP_PORT_LISTEN_BACKLOG) != 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
#endif
      retVal = LDAP_OPERATIONS_ERROR;
      BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                      "%s: listen() call failed with errno: %d", __func__, errno );
   }

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:

    if (*pSockfd >= 0)
    {
        tcp_close(*pSockfd);
        *pSockfd = -1;
    }
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, VDIR_SAFE_STRING(pszLocalErrMsg));
    goto cleanup;
}

/*
 *  We own pConnection and delete it when done.
 */
static
DWORD
ProcessAConnection(
   PVOID pArg
   )
{
   VDIR_CONNECTION *pConn = NULL;
   int            retVal = LDAP_SUCCESS;
   ber_tag_t      tag = LBER_ERROR;
   ber_len_t      len = 0;
   BerElement *   ber = NULL;
   ber_int_t      msgid = -1;
   PVDIR_OPERATION pOperation = NULL;
   int            reTries = 0;
   BOOLEAN                      bDownOpThrCount = FALSE;
   PVDIR_CONNECTION_CTX pConnCtx = NULL;

   // increment operation thread counter
   retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pOperationThrSyncCounter);
   BAIL_ON_VMDIR_ERROR(retVal);
   bDownOpThrCount = TRUE;

   pConnCtx = (PVDIR_CONNECTION_CTX)pArg;
   assert(pConnCtx);

   retVal = NewConnection(pConnCtx->sockFd, &pConn, pConnCtx->pSockbuf_IO);
   if (retVal != LDAP_SUCCESS)
   {
       VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: NewConnection [%d] failed with error: %d",
                        __func__, pConnCtx->sockFd, retVal);
       goto error;
   }

   while (TRUE)
   {
       if (VmDirdState() == VMDIRD_STATE_SHUTDOWN)
       {
           goto cleanup;
       }

      ber = ber_alloc();
      assert( ber != NULL);

      /* An LDAP request message looks like:
       * LDAPMessage ::= SEQUENCE {
       *                    messageID       MessageID,
       *                    protocolOp      CHOICE {
       *                       bindRequest     BindRequest,
       *                       unbindRequest   UnbindRequest,
       *                       searchRequest   SearchRequest,
       *                       ... },
       *                       controls       [0] Controls OPTIONAL }
       */


      // reset retry count
      reTries = 0;
      // Read complete LDAP request message (tag, length, and real message).
      while( reTries < MAX_NUM_OF_SOCK_READ_RETRIES )
      {
         if ((tag = ber_get_next( pConn->sb, &len, ber )) == LDAP_TAG_MESSAGE )
         {
            break;
         }

#ifdef _WIN32
         // in ber_get_next (liblber) call, sock_errset() call WSASetLastError()
         errno = WSAGetLastError();
         if ( errno == EWOULDBLOCK || errno == EAGAIN || errno == WSAETIMEDOUT)
#else
         if ( errno == EWOULDBLOCK || errno == EAGAIN)
#endif
         {
            if (gVmdirGlobals.dwLdapRecvTimeoutSec > 0 && ber->ber_len == 0)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_CONNS,
                    "%s: disconnecting peer (%s), idle > %d seconds",
                    __func__, pConn->szClientIP, gVmdirGlobals.dwLdapRecvTimeoutSec);
                retVal = LDAP_NOTICE_OF_DISCONNECT;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            //This may occur when not all data have recieved - set to EAGAIN/EWOULDBLOCK by ber_get_next,
            // and in such case ber->ber_len > 0;
            if (reTries > 0 && reTries % 5 == 0)
            {
                VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() failed with errno = %d, peer (%s), re-trying (%d)",
                                   __func__, errno , pConn->szClientIP, reTries);
            }
            VmDirSleep(200);
            reTries++;
            continue;
         }
         // Unexpected error case.
         if (errno == 0)
         {
             VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: ber_get_next() peer (%s) disconnected",
                 __func__, pConn->szClientIP);
         } else
         {
             VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_get_next() call failed with errno = %d peer (%s)",
                  __func__, errno, pConn->szClientIP);
         }
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read LDAP request messageID (tag, length (not returned since it is implicit/integer), and messageID value)
      if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_get_int() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      // Read protocolOp (tag) and length of the LDAP operation message, and leave the pointer at the beginning
      // of the LDAP operation message (to be parsed by PerformXYZ methods).
      if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR )
      {
         VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: ber_peek_tag() call failed." );
         retVal = LDAP_NOTICE_OF_DISCONNECT;
         BAIL_ON_VMDIR_ERROR( retVal );
      }

      retVal = VmDirNewOperation(ber, msgid, tag, pConn, &pOperation);
      if (retVal)
      {
          VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ProcessAConnection: NewOperation() call failed." );
          retVal = LDAP_OPERATIONS_ERROR;
      }
      BAIL_ON_VMDIR_ERROR( retVal );

      //
      // If this is a multi-stage operation don't overwrite the start time if it's already set.
      //
      pConn->SuperLogRec.iStartTime = pConn->SuperLogRec.iStartTime ? pConn->SuperLogRec.iStartTime : VmDirGetTimeInMilliSec();

      switch (tag)
      {
         case LDAP_REQ_BIND:
            retVal = VmDirPerformBind(pOperation);
            if (retVal != LDAP_SASL_BIND_IN_PROGRESS)
            {
                _VmDirCollectBindSuperLog(pConn, pOperation); // ignore error
            }

            break;

         case LDAP_REQ_ADD:
            retVal = VmDirPerformAdd(pOperation);
            break;

         case LDAP_REQ_SEARCH:
            retVal = VmDirPerformSearch(pOperation);
            break;

         case LDAP_REQ_UNBIND:
            retVal = VmDirPerformUnbind(pOperation);
            break;

         case LDAP_REQ_MODIFY:
             retVal = VmDirPerformModify(pOperation);
             break;

         case LDAP_REQ_DELETE:
             retVal = VmDirPerformDelete(pOperation);
             break;

         case LDAP_REQ_MODDN:
         case LDAP_REQ_COMPARE:
         case LDAP_REQ_ABANDON:
         case LDAP_REQ_EXTENDED:
            VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "ProcessAConnection: Operation is not yet implemented.." );
            pOperation->ldapResult.errCode = retVal = LDAP_UNWILLING_TO_PERFORM;
            // ignore following VmDirAllocateStringA error.
            VmDirAllocateStringA( "Operation is not yet implemented.", &pOperation->ldapResult.pszErrMsg);
            VmDirSendLdapResult( pOperation );
            break;

         default:
            pOperation->ldapResult.errCode = LDAP_PROTOCOL_ERROR;
            retVal = LDAP_NOTICE_OF_DISCONNECT;
            break;
      }

      pConn->SuperLogRec.iEndTime = VmDirGetTimeInMilliSec();
      VmDirOPStatisticUpdate(tag, pConn->SuperLogRec.iEndTime - pConn->SuperLogRec.iStartTime);

      if (tag != LDAP_REQ_BIND)
      {
         VmDirLogOperation(gVmdirGlobals.pLogger, tag, pConn, pOperation->ldapResult.errCode);

         _VmDirScrubSuperLogContent(tag, &pConn->SuperLogRec);
      }

      VmDirFreeOperation(pOperation);
      pOperation = NULL;

      ber_free( ber, 1);
      ber = NULL;

      if (retVal == LDAP_NOTICE_OF_DISCONNECT) // returned as a result of protocol parsing error.
      {
         // RFC 4511, section 4.1.1: If the server receives an LDAPMessage from the client in which the LDAPMessage
         // SEQUENCE tag cannot be recognized, the messageID cannot be parsed, the tag of the protocolOp is not
         // recognized as a request, or the encoding structures or lengths of data fields are found to be incorrect,
         // then the server **SHOULD** return the Notice of Disconnection, with the resultCode
         // set to protocolError, and **MUST** immediately terminate the LDAP session as described in Section 5.3.

         goto cleanup;
      }
   }

cleanup:
   if (retVal == LDAP_NOTICE_OF_DISCONNECT)
   {
      // Optionally send Notice of Disconnection with rs->err.
   }
   if (ber != NULL)
   {
      ber_free( ber, 1 );
   }
    VmDirDeleteConnection(&pConn);
    VMDIR_SAFE_FREE_MEMORY(pConnCtx);
    VmDirFreeOperation(pOperation);

    if (bDownOpThrCount)
    {
        VmDirSyncCounterDecrement(gVmdirGlobals.pOperationThrSyncCounter);
    }

    _VmDirFlowCtrlThrExit();

    // TODO: should we return dwError ?
    return 0;

error:
    goto cleanup;
}
예제 #15
0
파일: api_msg.c 프로젝트: apmorton/libxenon
/**
 * Internal helper function to close a TCP netconn: since this sometimes
 * doesn't work at the first attempt, this function is called from multiple
 * places.
 *
 * @param conn the TCP netconn to close
 */
static void
do_close_internal(struct netconn *conn)
{
  err_t err;
  u8_t shut, shut_rx, shut_tx, close;

  LWIP_ASSERT("invalid conn", (conn != NULL));
  LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
  LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
  LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
  LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);

  shut = conn->current_msg->msg.sd.shut;
  shut_rx = shut & NETCONN_SHUT_RD;
  shut_tx = shut & NETCONN_SHUT_WR;
  /* shutting down both ends is the same as closing */
  close = shut == NETCONN_SHUT_RDWR;

  /* Set back some callback pointers */
  if (close) {
    tcp_arg(conn->pcb.tcp, NULL);
  }
  if (conn->pcb.tcp->state == LISTEN) {
    tcp_accept(conn->pcb.tcp, NULL);
  } else {
    /* some callbacks have to be reset if tcp_close is not successful */
    if (shut_rx) {
      tcp_recv(conn->pcb.tcp, NULL);
      tcp_accept(conn->pcb.tcp, NULL);
    }
    if (shut_tx) {
      tcp_sent(conn->pcb.tcp, NULL);
    }
    if (close) {
      tcp_poll(conn->pcb.tcp, NULL, 4);
      tcp_err(conn->pcb.tcp, NULL);
    }
  }
  /* Try to close the connection */
  if (shut == NETCONN_SHUT_RDWR) {
    err = tcp_close(conn->pcb.tcp);
  } else {
    err = tcp_shutdown(conn->pcb.tcp, shut & NETCONN_SHUT_RD, shut & NETCONN_SHUT_WR);
  }
  if (err == ERR_OK) {
    /* Closing succeeded */
    conn->current_msg->err = ERR_OK;
    conn->current_msg = NULL;
    conn->state = NETCONN_NONE;
    /* Set back some callback pointers as conn is going away */
    conn->pcb.tcp = NULL;
    /* Trigger select() in socket layer. Make sure everybody notices activity
       on the connection, error first! */
    if (close) {
      API_EVENT(conn, NETCONN_EVT_ERROR, 0);
    }
    if (shut_rx) {
      API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    }
    if (shut_tx) {
      API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
    }
    /* wake up the application task */
    sys_sem_signal(&conn->op_completed);
  } else {
    /* Closing failed, restore some of the callbacks */
    /* Closing of listen pcb will never fail! */
    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
    tcp_sent(conn->pcb.tcp, sent_tcp);
    tcp_poll(conn->pcb.tcp, poll_tcp, 4);
    tcp_err(conn->pcb.tcp, err_tcp);
    tcp_arg(conn->pcb.tcp, conn);
    /* don't restore recv callback: we don't want to receive any more data */
  }
  /* If closing didn't succeed, we get called again either
     from poll_tcp or from sent_tcp */
}
예제 #16
0
파일: telnet_svc.c 프로젝트: k0059/yard-ice
int __attribute__((noreturn)) telnet_input_task(struct telnet_svc * tn)
{
	struct tcp_pcb * svc;
	struct tcp_pcb * tp;
	char buf[128];
	int sb_len;
	int len;
	char * src;
	int rem;
	int binary;
	int state;
	int c;
	struct tn_opt opt;
	unsigned int head;

	svc = tn->svc;

	for (;;) {

		INF("TELNET wating for connection.");
		DCC_LOG(LOG_TRACE, "TELNET: waiting for connection...");

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

		INF("TELNET connection accepted.");
		DCC_LOG(LOG_TRACE, "TELNET: accepted.");

		tn->tp  = tp;

		tn_opt_clr(&opt);
		sb_len = 0;
		binary = 0;
		state = TN_DATA;
		tn_opt_will(tp, &opt, TELOPT_SGA);
		tn_opt_do(tp, &opt, TELOPT_SGA);
		tn_opt_will(tp, &opt, TELOPT_ECHO);
		tn_opt_will(tp, &opt, TELOPT_BINARY);
		tn_opt_do(tp, &opt, TELOPT_BINARY);

		head = tn->rx.head;

		for (;;) {

			if (head != tn->rx.tail) {
				/* update the head */
				tn->rx.head = head;
				DCC_LOG1(LOG_TRACE, "rx nonempty: head=%d", head);
				/* signal the head update */
				thinkos_flag_give(tn->rx.nonempty_flag);
			}

			/* receive data form network */
			if ((len = tcp_recv(tp, buf, 128)) <= 0) {
				DCC_LOG1(LOG_WARNING, "tcp_recv(): %d", len);
				break;
			}

			DCC_LOG1(LOG_TRACE, "recv: %d", len);

			/* set the input processing pointer */
			src = buf;
			/* input remaining (to be processed) bytes */
			rem = len;

			while (rem > 0) {
				c = *src++;
				rem--;

				if (state == TN_DATA) {
					if (c == IAC) {
						state = TN_IAC_RCVD;
					} else {
						if ((binary) || ((c >= 3) && (c < 127))) {
							/* ASCII characters */
							DCC_LOG1(LOG_TRACE, "rx nonempty: head=%d", head);

							/* buffer is full */
							if (head == (tn->rx.tail + TELNET_SVC_RX_BUF_LEN)) {
								/* update the head */
								tn->rx.head = head;
								/* signal the head update */
								thinkos_flag_give(tn->rx.nonempty_flag);
								
								/* wait for space in the input buffer */
								while (1) {
									if (head < (tn->rx.tail + 
												 TELNET_SVC_RX_BUF_LEN)) {
										break;
									}
									thinkos_flag_take(tn->rx.nonfull_flag);
								}
							} 

							tn->rx.buf[head++ % TELNET_SVC_RX_BUF_LEN] = c;

						} 
					}
					continue;
				}

				/* handles TELNET inputs options */
				switch (state) {

				case TN_IAC_RCVD:
					switch (c) {
					case IAC:
						state = TN_DATA;
						break;
					case DONT:
						state = TN_DONT_RCVD;
						break;
					case DO:
						state = TN_DO_RCVD;
						break;
					case WONT:
						state = TN_WONT_RCVD;
						break;
					case WILL:
						state = TN_WILL_RCVD;
						break;
					case SB:
						state = TN_SUBOPTION_ID;
						break;
					case EL:
					case EC:
					case AYT:
					case AO:
					case IP:
					case BREAK:
					case DM:
					case NOP:
					case SE:
					case EOR:
					case ABORT:
					case SUSP:
					case xEOF:
					default:
						state = TN_DATA;
						break;
					}
					break;

				case TN_DONT_RCVD:
					DCC_LOG1(LOG_TRACE, "DONT %s", TELOPT(c));
					tn_opt_wont(tp, &opt, c);
					state = TN_DATA;
					break;

				case TN_DO_RCVD:
					DCC_LOG1(LOG_TRACE, "DO %s", TELOPT(c));
					switch (c) {

					case TELOPT_SGA:
						tn_opt_will(tp, &opt, c);
						break;

					case TELOPT_ECHO:
						tn_opt_will(tp, &opt, c);
						break;

					case TELOPT_BINARY:
						tn_opt_will(tp, &opt, c);
						break;

					default:
						tn_opt_wont(tp, &opt, c);
					}

					state = TN_DATA;
					break;

				case TN_WONT_RCVD:
					DCC_LOG1(LOG_TRACE, "WONT %s", TELOPT(c));
					tn_opt_dont(tp, &opt, c);
					state = TN_DATA;
					break;

				case TN_WILL_RCVD:
					DCC_LOG1(LOG_TRACE, "WILL %s", TELOPT(c));

					switch (c) {
					case TELOPT_ECHO:
						tn_opt_dont(tp, &opt, c);
						break;

					case TELOPT_SGA:
						tn_opt_do(tp, &opt, c);
						break;

					case TELOPT_BINARY:
						tn_opt_do(tp, &opt, c);
						binary = 1;
						break;

					default:
						tn_opt_dont(tp, &opt, c);
					}

					state = TN_DATA;
					break;

				case TN_SUBOPTION_ID:
					state = TN_SUBOPTION;
					break;

				case TN_SUBOPTION:
					if (c == IAC)
						state = TN_SB_IAC_RCVD;
					if (sb_len < TN_SB_BUF_LEN) {
						DCC_LOG1(LOG_TRACE, "suboption: %d", c);
					}
//					sb_buf[sb_len++] = c;
					break;

				case TN_SB_IAC_RCVD:
					if (c == SE) {
						state = TN_DATA;
//						tn_suboption(cpc, sb_buf, sb_len);
					} else {
						state = TN_SUBOPTION;
//						sb_buf[sb_len++] = c;
					}
					break;

				case TN_INVALID_SUBOPTION:
					if (c == IAC)
						state = TN_INVALID_SB_IAC_RCVD;
					break;

				case TN_INVALID_SB_IAC_RCVD:
					if (c == SE)
						state = TN_DATA;
					else
						state = TN_INVALID_SUBOPTION;
					break;

				default:
					DCC_LOG1(LOG_WARNING, "invalid state: %d!!", state);
					break;
				}

			}

		}

		DCC_LOG(LOG_TRACE, "close...");

		tcp_close(tp);
		INF("TELNET connection closed.");
		tn->tp  = NULL;
	}

	DCC_LOG(LOG_ERROR, "thread loop break!!!");
	for(;;);
}
예제 #17
0
파일: net.c 프로젝트: stoned7/kopou
int main(int argc, char **argv)
{
	int server;
	int efd;
	struct epoll_event ev, events[10];


	server = tcp_create_listener(7878, 1024, 0);
	if (server == TCP_ERR) {
		printf("server creation fail\n");
		return EXIT_FAILURE;
	}

	efd = epoll_create(10);
	if (efd == -1) {
		perror("epoll_create");
		exit(EXIT_FAILURE);
	}
	ev.events = EPOLLIN;
	ev.data.fd = server;
	epoll_ctl(efd, EPOLL_CTL_ADD, server, &ev);
	printf("server listening ...\n");

	int etfd;
	int n;
	long ecounter = 0;
	while(1) {
		etfd = epoll_wait(efd, events, 10, -1);
		ecounter++;
		if (etfd == -1) {
			printf("ecounter:%ld\n", ecounter);
			perror("epoll_wait");
			exit(EXIT_FAILURE);
		}

		for (n = 0; n < etfd; ++n) {
			if ((events[n].events & EPOLLERR) ||
				(events[n].events & EPOLLHUP))
				 //&& ((!events[n].events & EPOLLIN)
				 //|| (!events[n].events & EPOLLOUT))
				{
					printf("ecounter:%ld\n", ecounter);
					perror("epoll error");
					close (events[n].data.fd);
					continue;
				}

			if (events[n].data.fd == server) {
				printf("ecounter:%ld\n", ecounter);
				char ip[64];
				int port;
				int tryagain;
				int cli = tcp_accept(server, ip, 64, &port, 1,
						&tryagain);
				if (cli == TCP_ERR) {
					printf("tryagain: %d\n", tryagain);
					printf("accept(): %s\n", strerror(errno));
					continue;
				}
				//tcp_set_keepalive(cli, 10);
				printf("-----> Client: %s:%d\n", ip, port);
				ev.events = EPOLLIN;
				ev.data.fd = cli;
				epoll_ctl(efd, EPOLL_CTL_ADD, cli, &ev);
			}
			else {
				if (events[n].events & EPOLLIN) {
					printf("ecounter:%ld\n", ecounter);
					printf("%d ready for read\n", events[n].data.fd);

					int cli = events[n].data.fd;
					int tryagain;
					char buf[16];
					int isreadonce = 0;
					ssize_t nread;
					memset(buf, '\0', 16);
					nread = tcp_read(cli, buf, 16, &tryagain);
					if (nread > 0) {
						printf("Read: %zd:%d:%s\n", nread,tryagain, buf);
						ev.events = events[n].events;
						ev.events |= EPOLLOUT;
						ev.data.fd = events[n].data.fd;
						int rct = epoll_ctl(efd, EPOLL_CTL_MOD, ev.data.fd, &ev);
						if (rct == -1)
							perror("r:epoll_ctl_mod");
					} else {
						if (tryagain) {
							printf("completed reading: %zd, tryagain:%d\n",
							nread, tryagain);
							printf("read(): %s\n", strerror(errno));
							break;
						} else {
							printf("client down: %zd\n", nread);
							printf("read(): %s\n", strerror(errno));
							tcp_close(cli);
							break;
						}
					}
				}

				if (events[n].events & EPOLLOUT) {
					printf("ecounter:%ld\n", ecounter);
					printf("%d ready for write\n",events[n].data.fd);
					int tryagain;
					char *buf = "helloresponse";
					ssize_t written = tcp_write(events[n].data.fd,  buf, 13, &tryagain);
					printf("written: %zd, tryagain: %d\n", written, tryagain);
					ev.events = events[n].events;
					ev.events = EPOLLIN;
					ev.data.fd = events[n].data.fd;
					int rct = epoll_ctl(efd, EPOLL_CTL_MOD, ev.data.fd, &ev);
					if (rct == -1)
						perror("w:epoll_ctl_mod");

				}
			}
		}
	}

	return EXIT_SUCCESS;
}
예제 #18
0
파일: telnet_svc.c 프로젝트: k0059/yard-ice
int telnet_svc_release(struct telnet_svc * tn)
{
	return tcp_close(tn->tp);
}
예제 #19
0
int main(void) {

    char client_buf[1], server_buf[1];
    char *eth, *ip1, *ip2;

    int pid, status;

    unsigned char j, v;

    ipaddr_t saddr;

    eth = getenv("ETH");
    if (!eth) {
        fprintf(stderr, "The ETH environment variable must be set!\n");
        return 1;
    }

    ip1 = getenv("IP1");
    ip2 = getenv("IP2");
    if ((!ip1)||(!ip2)) {
        fprintf(stderr, "The IP1 and IP2 environment variables must be set!\n");
        return 1;
    }

    pid = fork();

    if (pid == -1) {
        fprintf(stderr, "Unable to fork client process\n");
        return 1;
    }

    if (pid == 0) {

        /* Client process running in $IP1 */

  
        eth[0] = '1';
        /*ip_init();*/

        if (tcp_socket() != 0) {
            fprintf(stderr, "Client: Opening socket failed\n");
            return 1;
        }

        if (tcp_connect(inet_aton(ip2), 80) != 0) {
            fprintf(stderr, "Client: Connecting to server failed\n");
            return 1;
        }
        
        for (v=0; v<255; v++) {
            client_buf[0] = v;
            if (tcp_write(client_buf, 1) != 1) {
                fprintf(stderr, "Client: Writing ASCII character %u failed (", v);
                
                return 1;
            }
            printf("Client: Sent ASCII character %u (", v);
            
        }
        /* send last byte (255)*/
        client_buf[0] = v;
        if (tcp_write(client_buf, 1) != 1) {
            fprintf(stderr, "Client: Writing ASCII character %u failed (", v);
            
            return 1;
        }
        printf("Client: Sent ASCII character %u (", v);
        

        
        
        if (tcp_close() != 0) {
            fprintf(stderr, "Client: Closing connection failed\n");
            return 1;
        }

        signal(SIGALRM, alarm_handler);
        alarm(5);

        while (tcp_read(server_buf, 4) > 0) {}

        alarm(0);

        return 0;

    } else {

        /* Server process running in $IP2 */

        eth[0]='2';

        if (tcp_socket() != 0) {
            fprintf(stderr, "Server: Opening socket failed\n");
            return 1;
        }

        signal(SIGALRM, alarm_handler);
        alarm(5);

        if (tcp_listen(80, &saddr) < 0) {
            fprintf(stderr, "Server: Listening for client failed\n");
            return 1;
        }

        alarm(0);

        for (j=0; j<255; j++) {

            signal(SIGALRM, alarm_handler);
            alarm(5);

            if (tcp_read(server_buf, 1) < 0) {
                fprintf(stderr, "Server: Reading 1 byte failed\n");
                return 1;
            }

            alarm(0);

            printf("Server: Found byte %u\n", (tcp_u8t) server_buf[0]);

            if (((tcp_u8t)server_buf[0]) != j) {
                fprintf(stderr, "Server: Reading ASCII character %u failed\n", j);
                fprintf(stderr, "Server: Found ASCII character %u\n", server_buf[0]);
                return 1;
            }

        }
        signal(SIGALRM, alarm_handler);
        alarm(5);

        if (tcp_read(server_buf, 1) < 0) {
            fprintf(stderr, "Server: Reading 1 byte failed\n");
            return 1;
        }

        alarm(0);

        fprintf(stderr, "Server: Found byte %u\n", (tcp_u8t) server_buf[0]);

        if (((tcp_u8t)server_buf[0]) != j) {
            fprintf(stderr, "Server: Reading ASCII character %u failed\n", j);
            fprintf(stderr, "Server: Found ASCII character %u\n", server_buf[0]);
            return 1;
        }






        if (tcp_close() != 0) {
            fprintf(stderr, "Server: Closing connection failed\n");
            return 1;
        }

        signal(SIGALRM, alarm_handler);
        alarm(5);

        while (tcp_read(server_buf, 4) > 0) {}

        alarm(0);

        /* Wait for client process to finish */
        while (wait(&status) != pid);

        return 0;

    }
    
}
예제 #20
0
/**
  * @brief  Called when a data is received on the telnet connection
  * @param  arg :the user argument
  * @param  pcb :the tcp_pcb that has received the data
  * @param  p   :the packet buffer
  * @param  err :the error value linked with the received data
  * @retval error value
  */
static err_t HelloWorld_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
    struct pbuf *q;
    struct name *name = (struct name *)arg;
    int done;
    char *c;
    int i;
 
    /* We perform here any necessary processing on the pbuf */
    if (p != NULL) 
    {        
        /* We call this function to tell the LwIp that we have processed the data */
        /* This lets the stack advertise a larger window, so more data can be received*/
        tcp_recved(pcb, p->tot_len);

        /* Check the name if NULL, no data passed, return withh illegal argument error */
        if(!name) 
        {
            pbuf_free(p);
            return ERR_ARG;
        }

        done = 0;
        for(q=p; q != NULL; q = q->next) 
        {
            c = q->payload;
            for(i=0; i<q->len && !done; i++) 
            {
                done = ((c[i] == '\r') || (c[i] == '\n'));
                if(name->length < MAX_NAME_SIZE) 
                {
                    name->bytes[name->length++] = c[i];
                }
            }
        }
        if(done) 
        {
            if(name->bytes[name->length-2] != '\r' || name->bytes[name->length-1] != '\n') 
            {
                if((name->bytes[name->length-1] == '\r' || name->bytes[name->length-1] == '\n') 
                    && (name->length+1 <= MAX_NAME_SIZE)) 
                {
                    name->length += 1;
                } 
                else if(name->length+2 <= MAX_NAME_SIZE) 
                {
                    name->length += 2;
                } 
                else 
                {
                    name->length = MAX_NAME_SIZE;
                }

                name->bytes[name->length-2] = '\r';
                name->bytes[name->length-1] = '\n';
            }
            tcp_write(pcb, HELLO, strlen(HELLO), 1);

            tcp_write(pcb, name->bytes, name->length, TCP_WRITE_FLAG_COPY);
            printf("\n\rGigadevice\n\rTelnet %s %s", HELLO, name->bytes);
            name->length = 0;
        }
    
        /* End of processing, we free the pbuf */
        pbuf_free(p);
    }  
    else if (err == ERR_OK) 
    {
        /* When the pbuf is NULL and the err is ERR_OK, the remote end 
           is closing the connection. */
        /* We free the allocated memory and we close the connection */
        mem_free(name);
        return tcp_close(pcb);
    }
    return ERR_OK;
}
예제 #21
0
파일: http.c 프로젝트: Bob4ik888/WebRadio
unsigned int http_sendfile(unsigned int idx, const char *name, unsigned char *tx)
{
  unsigned int len=0, i;

  if(name) //start transfer -> add http header
  {
    http_table[idx].status = HTTP_SEND;
    http_table[idx].file   = http_fid(name, &http_table[idx].fparam);
    http_table[idx].ftype  = http_ftype(http_table[idx].file);
    http_table[idx].flen   = http_flen(http_table[idx].file, http_table[idx].fparam);
    http_table[idx].fpos   = 0;
    http_table[idx].fparse = 0;

    if(http_table[idx].flen == 0) //file not found
    {
      http_table[idx].status = HTTP_CLOSED;
      len = sprintf((char*)tx, HTTP_404_HEADER"Error 404 Not found\r\n\r\n");
      tcp_send(idx, len, 0);
      tcp_close(idx);
      return len;
    }
    else //file found -> send http header
    {
      switch(http_table[idx].ftype)
      {
        case HTML_FILE:
          len = sprintf((char*)tx, HTTP_HTML_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case XML_FILE:
          len = sprintf((char*)tx, HTTP_XML_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case JS_FILE:
          len = sprintf((char*)tx, HTTP_JS_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case CSS_FILE:
          len = sprintf((char*)tx, HTTP_CSS_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case TXT_FILE:
          len = sprintf((char*)tx, HTTP_TXT_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case ICON_FILE:
          len = sprintf((char*)tx, HTTP_ICON_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case GIF_FILE:
          len = sprintf((char*)tx, HTTP_GIF_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
        case JPEG_FILE:
          len = sprintf((char*)tx, HTTP_JPEG_HEADER"%i\r\n\r\n", http_table[idx].flen);
          tx += len;
          break;
      }
    }
  }

  if(http_table[idx].flen) //file found
  {
    switch(http_table[idx].ftype)
    {
      //dynamic content
      case HTML_FILE:
      case XML_FILE:
        i = http_fparse((char*)tx, http_table[idx].file, &http_table[idx].fparse, (ETH_MTUSIZE-IP_HEADERLEN-TCP_HEADERLEN-MAX_ADDR-100), http_table[idx].fparam);
        http_table[idx].fpos += i;
        len += i;
        break;
      //static content
      case JS_FILE:
      case CSS_FILE:
      case TXT_FILE:
      case ICON_FILE:
      case GIF_FILE:
      case JPEG_FILE:
        i = http_fdata(tx, http_table[idx].file, http_table[idx].fpos, (ETH_MTUSIZE-IP_HEADERLEN-TCP_HEADERLEN-MAX_ADDR-100));
        http_table[idx].fpos += i;
        len += i;
        break;
    }
    tcp_send(idx, len, 0);
    if((http_table[idx].fpos >= http_table[idx].flen) || (len == 0))
    {
      http_close(idx);
      tcp_close(idx);
    }
  }

  return len;
}
예제 #22
0
int main(void)
{
	int ret, sd, ii;
	gnutls_session_t session;
	char buffer[MAX_BUF + 1];
	gnutls_certificate_credentials_t xcred;
	// Allow connections to servers that have X509
	const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };

	gnutls_global_init();

	gnutls_global_set_log_function(tls_log_func);
	gnutls_global_set_log_level(2);

	// X509 stuff
	gnutls_certificate_allocate_credentials(&xcred);

	// sets the trusted cas file
//	gnutls_certificate_set_x509_trust_file(xcred, CAFILE,
//					       GNUTLS_X509_FMT_PEM);

	// Initialize TLS session 
	gnutls_init(&session, GNUTLS_CLIENT);

	// Use default priorities
	gnutls_set_default_priority(session);
	gnutls_certificate_type_set_priority(session, cert_type_priority);

	// put the x509 credentials to the current session
	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);

	// connect to the peer
	sd = tcp_connect();

	// pass the socket descriptor in non blocking
	tcp_nonblock(sd);
	// set all the custom read/write function
	gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) sd);
	gnutls_transport_set_pull_function(session, tcp_read);
	gnutls_transport_set_push_function(session, tcp_write);

	// Perform the TLS handshake - until completed or error
	do {
		ret = gnutls_handshake(session);
		if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
			usleep(1000 * 10);
	}
	while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

	if(ret < 0) {
		fprintf(stderr, "*** Handshake failed\n");
		goto end;
	} else {
		printf("- Handshake was completed\n");
	}
	
	// log to debug
	print_info(session);

	ssize_t		written_len;
	written_len	= gnutls_record_send(session, MSG, strlen(MSG));
	printf("written_len=%d\n", written_len);

	do{
		ret = gnutls_record_recv(session, buffer, MAX_BUF);
		if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
			usleep(1000 * 10);
	}while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

	if(ret == 0) {
		printf("- Peer has closed the TLS connection\n");
		goto end;
	} else if(ret < 0) {
		fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
		goto end;
	}

	printf("- Received %d bytes: ", ret);
	for(ii = 0; ii < ret; ii++) {
		fputc(buffer[ii], stdout);
	}
	fputs("\n", stdout);

	gnutls_bye(session, GNUTLS_SHUT_RDWR);

      end:
	tcp_close(sd);
	gnutls_deinit(session);
	gnutls_certificate_free_credentials(xcred);
	gnutls_global_deinit();
	return 0;
}
예제 #23
0
int main(void)
{
	/* credentials */
	gnutls_anon_client_credentials_t c_anoncred;
	gnutls_certificate_credentials_t c_certcred;

	gnutls_session_t client;
	int sd, i;

	/* General init. */
	global_init();
	ecore_init();
//  gnutls_global_set_log_function (tls_log_func);
//  gnutls_global_set_log_level (6);

	/* Init client */
	gnutls_anon_allocate_client_credentials(&c_anoncred);
	gnutls_certificate_allocate_credentials(&c_certcred);


	for (i = 0; i < 5; i++) {

		gnutls_init(&client, GNUTLS_CLIENT);
		/* set very specific priorities */

		gnutls_handshake_set_timeout(client, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

		gnutls_priority_set_direct(client, "NORMAL:+ANON-DH",
					   NULL);
		gnutls_credentials_set(client, GNUTLS_CRD_ANON,
				       c_anoncred);
		gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				       c_certcred);
		gnutls_server_name_set(client, GNUTLS_NAME_DNS,
				       "localhost", strlen("localhost"));

		/* connect to the peer
		 */
		sd = tcp_connect();

		/* associate gnutls with socket */
		gnutls_transport_set_int(client, sd);
		/* add a callback for data being available for send/receive on socket */
		if (!ecore_main_fd_handler_add
		    (sd, ECORE_FD_READ | ECORE_FD_WRITE,
		     (Ecore_Fd_Cb) _process_data, client, NULL, NULL)) {
			print("could not create fd handler!");
			exit(1);
		}
		/* begin main loop */
		ecore_main_loop_begin();

		gnutls_bye(client, GNUTLS_SHUT_RDWR);

		gnutls_deinit(client);

		tcp_close(sd);
	}

	gnutls_anon_free_client_credentials(c_anoncred);
	gnutls_certificate_free_credentials(c_certcred);

	return 0;
}
예제 #24
0
int usys_accept(int *err, uuprocess_t *u, int fd, struct sockaddr *acc_addr, socklen_t *addrlen)
{
    if( u == 0 )
    {
        *err = ENOTSOCK; // TODO correct?
        return -1;
    }

    CHECK_FD(fd);
    struct uufile *f = GETF(fd);

    struct uusocket *us = f->impl;

    // todo require UU_FILE_FLAG_ACCEPTABLE
    if( ! (f->flags & (UU_FILE_FLAG_NET|UU_FILE_FLAG_TCP)) )
    {
        *err = ENOTSOCK;
        return -1;
    }

    //us->addr = my_addr;

    void *new_socket = NULL;
    i4sockaddr tmp_addr;

    int pe = tcp_accept(us->prot_data, &tmp_addr, &new_socket);

    if( *addrlen >= (int)sizeof(struct sockaddr_in) )
    {
        /*
        struct sockaddr_in ia;

        ia.sin_len = sizeof(struct sockaddr_in);
        ia.sin_port = tmp_addr.port;
        ia.sin_addr.s_addr = NETADDR_TO_IPV4(tmp_addr.addr);
        ia.sin_family = PF_INET;

        *((struct sockaddr_in *)acc_addr) = ia;
        *addrlen = sizeof(struct sockaddr_in);
        */
        if( sockaddr_int2unix( acc_addr, addrlen, &tmp_addr ) )
            *addrlen = 0;
    }
    else
        *addrlen = 0;

    // TODO translate!
    if( pe )
    {
        *err = ECONNABORTED;
        return -1;
    }

    struct uusocket *rus = calloc(1, sizeof(struct uusocket));
    if(rus == 0)
    {
        tcp_close( new_socket );
        *err = ENOMEM;
        return -1;
    }



    uufile_t *rf = create_uufile();
    assert(f);

    rf->ops = &tcpfs_fops;

    rf->pos = 0;
    rf->fs = &tcp_fs;
    rf->impl = rus;
    rf->flags = UU_FILE_FLAG_NET|UU_FILE_FLAG_TCP;

    int rfd = uu_find_fd( u, rf );

    if( rfd < 0 )
    {
        tcp_close( new_socket );
        unlink_uufile( f );
        free( us );
        *err = EMFILE;
        return -1;
    }

    return *err ? -1 : rfd;
}
예제 #25
0
void
tcp_timer_2msl(void *xtp)
{
	struct tcpcb *tp = xtp;
	struct inpcb *inp;
	CURVNET_SET(tp->t_vnet);
#ifdef TCPDEBUG
	int ostate;

	ostate = tp->t_state;
#endif
	INP_INFO_RLOCK(&V_tcbinfo);
	inp = tp->t_inpcb;
	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
	INP_WLOCK(inp);
	tcp_free_sackholes(tp);
	if (callout_pending(&tp->t_timers->tt_2msl) ||
	    !callout_active(&tp->t_timers->tt_2msl)) {
		INP_WUNLOCK(tp->t_inpcb);
		INP_INFO_RUNLOCK(&V_tcbinfo);
		CURVNET_RESTORE();
		return;
	}
	callout_deactivate(&tp->t_timers->tt_2msl);
	if ((inp->inp_flags & INP_DROPPED) != 0) {
		INP_WUNLOCK(inp);
		INP_INFO_RUNLOCK(&V_tcbinfo);
		CURVNET_RESTORE();
		return;
	}
	KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0,
		("%s: tp %p tcpcb can't be stopped here", __func__, tp));
	KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0,
		("%s: tp %p 2msl callout should be running", __func__, tp));
	/*
	 * 2 MSL timeout in shutdown went off.  If we're closed but
	 * still waiting for peer to close and connection has been idle
	 * too long delete connection control block.  Otherwise, check
	 * again in a bit.
	 *
	 * If in TIME_WAIT state just ignore as this timeout is handled in
	 * tcp_tw_2msl_scan().
	 *
	 * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed, 
	 * there's no point in hanging onto FIN_WAIT_2 socket. Just close it. 
	 * Ignore fact that there were recent incoming segments.
	 */
	if ((inp->inp_flags & INP_TIMEWAIT) != 0) {
		INP_WUNLOCK(inp);
		INP_INFO_RUNLOCK(&V_tcbinfo);
		CURVNET_RESTORE();
		return;
	}
	if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
	    tp->t_inpcb && tp->t_inpcb->inp_socket && 
	    (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
		TCPSTAT_INC(tcps_finwait2_drops);
		tp = tcp_close(tp);             
	} else {
		if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) {
			if (!callout_reset(&tp->t_timers->tt_2msl,
			   TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) {
				tp->t_timers->tt_flags &= ~TT_2MSL_RST;
			}
		} else
		       tp = tcp_close(tp);
       }

#ifdef TCPDEBUG
	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
			  PRU_SLOWTIMO);
#endif
	TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);

	if (tp != NULL)
		INP_WUNLOCK(inp);
	INP_INFO_RUNLOCK(&V_tcbinfo);
	CURVNET_RESTORE();
}
예제 #26
0
파일: net_posix.c 프로젝트: Rautz/showtime
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct hostent *hp;
  char *tmphstbuf;
  int fd, val, r, err, herr;
  const char *errtxt;
#if !defined(__APPLE__)
  struct hostent hostbuf;
  size_t hstbuflen;
  int res;
#endif
  struct sockaddr_in6 in6;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

#if defined(__APPLE__)
    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    /* TODO: AF_INET6 */
    hp = gethostbyname(hostname);
    if(hp == NULL)
      herr = h_errno;
#else
    hstbuflen = 1024;
    tmphstbuf = malloc(hstbuflen);

    while((res = gethostbyname_r(hostname, &hostbuf, tmphstbuf, hstbuflen,
				 &hp, &herr)) == ERANGE) {
      hstbuflen *= 2;
      tmphstbuf = realloc(tmphstbuf, hstbuflen);
    }
#endif
    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      memcpy(&in.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    case AF_INET6:
      memset(&in6, 0, sizeof(in6));
      in6.sin6_family = AF_INET6;
      in6.sin6_port = htons(port);
      memcpy(&in6.sin6_addr, hp->h_addr_list[0], sizeof(struct in6_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in6));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }
  if(r == -1) {
    if(errno == EINPROGRESS) {
      struct pollfd pfd;

      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = poll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	close(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
	close(fd);
	return NULL;
      }

      getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    close(fd);
    return NULL;
  }
  
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);

  val = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);
  

  if(ssl) {
#if ENABLE_OPENSSL
    if(showtime_ssl_ctx != NULL) {
      char errmsg[120];

      if((tc->ssl = SSL_new(showtime_ssl_ctx)) == NULL) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }
      if(SSL_set_fd(tc->ssl, tc->fd) == 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL fd: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      if(SSL_connect(tc->ssl) <= 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL connect: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      SSL_set_mode(tc->ssl, SSL_MODE_AUTO_RETRY);
      tc->read = ssl_read;
      tc->write = ssl_write;
    } else
#elif ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
예제 #27
0
static void
client (void)
{
  int ret, sd, ii;
  gnutls_session_t session;
  char buffer[MAX_BUF + 1];
  gnutls_psk_client_credentials_t pskcred;
  const gnutls_datum_t key = { (char *) "DEADBEEF", 8 };

  gnutls_global_init ();

  gnutls_global_set_log_function (tls_log_func);
//  if (debug)
//    gnutls_global_set_log_level (99);

  gnutls_psk_allocate_client_credentials (&pskcred);
  gnutls_psk_set_client_credentials (pskcred, "test", &key,
				     GNUTLS_PSK_KEY_HEX);

  /* Initialize TLS session
   */
  gnutls_init (&session, GNUTLS_CLIENT);

  /* Use default priorities */
  gnutls_set_default_priority (session);

  /* put the anonymous credentials to the current session
   */
  gnutls_credentials_set (session, GNUTLS_CRD_PSK, pskcred);

  /* connect to the peer
   */
  sd = tcp_connect ();

  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);

  /* Perform the TLS handshake
   */
  ret = gnutls_handshake (session);

  if (ret < 0)
    {
      fail ("client: Handshake failed\n");
      gnutls_perror (ret);
      goto end;
    }
  else
    {
      if (debug)
	success ("client: Handshake was completed\n");
    }

  gnutls_record_send (session, MSG, strlen (MSG));

  ret = gnutls_record_recv (session, buffer, MAX_BUF);
  if (ret == 0)
    {
      if (debug)
	success ("client: Peer has closed the TLS connection\n");
      goto end;
    }
  else if (ret < 0)
    {
      fail ("client: Error: %s\n", gnutls_strerror (ret));
      goto end;
    }

  if (debug)
    {
      printf ("- Received %d bytes: ", ret);
      for (ii = 0; ii < ret; ii++)
	fputc (buffer[ii], stdout);
      fputs ("\n", stdout);
    }

  gnutls_bye (session, GNUTLS_SHUT_RDWR);

end:

  tcp_close (sd);

  gnutls_deinit (session);

  gnutls_psk_free_client_credentials (pskcred);

  gnutls_global_deinit ();
}
예제 #28
0
void loop_process(int cfd) {

	DEBUG(" Child=======>  In child!\n");
	int acceptfd;
	int recved;
	fd_set readfds;
	int delay = 300;
	struct timeval timeout;
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	struct sockaddr_in client_addr;
	socklen_t sock_len = sizeof(struct sockaddr);
	char buffer[512];
	ctl_hdr *hdr;
	uint16 ret_code = 0;

	//服务器对web服务器的回复报文
	struct replay_packet replay;
	replay.head.len = 2;
	replay.head.encrpyt = ENCRPYT_NO;
	replay.head.mo = MO_SERVER;
	replay.head.ttl = 0;
	replay.head.ki = KI_REPLAY;

	while (1) {
		DEBUG(" Child=======>  Waiting for connect! In child thread!\n");
		FD_ZERO(&readfds);
		FD_SET(cfd, &readfds);
		timeout.tv_sec = delay;
		timeout.tv_usec = 0;
		int tt;
		switch(tt = select(cfd + 1, &readfds, NULL, NULL, &timeout)) {
		case -1:
			//error
			continue;
			break;
		default:
			if (FD_ISSET(cfd, &readfds)) {
				acceptfd = accept(cfd,(struct sockaddr *) &client_addr, &sock_len);
				if (acceptfd <=0)  {
					DEBUG(" Child=======>  accept failed!\n");
					exit(-1);
				}
				recved = recv(acceptfd, buffer, sizeof(buffer), 0);
				DEBUG(" Child=======>  Listen socket:  %d\tAccept socket:  %d\n", cfd, acceptfd);
				struct common_packet * common = (struct common_packet *)buffer;

				DEBUG(" Child=======>  Received KI:  %d\n", common->head.ki);
				DEBUG(" Child=======>  Received data length:  %d\n", recved);

				if (recved > 0) {
					hdr = (ctl_hdr *)buffer;
					//如果是登录请求
					if (hdr->ki == KI_LOGIN) {
						//判断用户名和密码是否正确
						struct register_struct * user_struct = (struct register_struct *)buffer;
						if (user_check(&(user_struct->user_struct)) == 0) {
							//登录成功
							replay.data = RPL_LOGIN_SUCCESS;
							replay.head.extent = 111;
							writen(acceptfd, (void *)&replay, sizeof(replay));
							DEBUG(" Child=======>  Login successful!\n");
							tcp_close(acceptfd);
						} else {
							replay.data = RPL_LOGIN_FALLED;
							writen(acceptfd, (void *)&replay, sizeof(replay));
							DEBUG(" Child=======>  Login failed!\n");
							tcp_close(acceptfd);
						}
					} else if (hdr->ki == KI_REGISTER) {
						//用户注册
						struct register_struct * user_struct = (struct register_struct *)buffer;
						if (user_register(&(user_struct->user_struct)) == 0) {
							//注册成功
							replay.data = RPL_REGISTER_SUCCESS;
							writen(acceptfd, (void *)&replay, sizeof(replay));
							DEBUG("Register User Successful\n");
							tcp_close(acceptfd);
						} else {
							replay.data = RPL_REGISTER_FALLED;
							writen(acceptfd, (void *)&replay, sizeof(replay));
							DEBUG("Register User Failed\n");
							tcp_close(acceptfd);
						}
						//如果是发送的数据包,判断extent值,看是否已登录成功
					} else {
						hdr = (ctl_hdr *)buffer;
						DEBUG(" Child=======>  extent is : %d\tttl is : %d\n", hdr->extent, hdr->ttl);
						if ((hdr->extent) == 111) {
							ret_code = proc_packet(buffer, acceptfd);
							if (ret_code == RPL_NO_COMMON_REPLAY) {

							} else {
								replay.data = ret_code;
								writen(acceptfd, (void *)&replay, sizeof(replay));
							}
							tcp_close(acceptfd);
						}
					}
				}
			}
			break;
		}
		tcp_close(acceptfd);
		DEBUG(" Child=======>  tt is %d\n", tt);
	}
}
예제 #29
0
int
main (void)
{
    int ret, sd, ii;
    gnutls_session_t session;
    gnutls_priority_t priorities_cache;
    char buffer[MAX_BUF + 1];
    gnutls_certificate_credentials_t xcred;
    /* Allow connections to servers that have OpenPGP keys as well.
     */

    gnutls_global_init ();

    load_keys ();

    /* X509 stuff */
    gnutls_certificate_allocate_credentials (&xcred);

    /* priorities */
    gnutls_priority_init( &priorities_cache, "NORMAL", NULL);


    /* sets the trusted cas file
     */
    gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);

    gnutls_certificate_client_set_retrieve_function (xcred, cert_callback);

    /* Initialize TLS session
     */
    gnutls_init (&session, GNUTLS_CLIENT);

    /* Use default priorities */
    gnutls_priority_set (session, priorities_cache);

    /* put the x509 credentials to the current session
     */
    gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);

    /* connect to the peer
     */
    sd = tcp_connect ();

    gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);

    /* Perform the TLS handshake
     */
    ret = gnutls_handshake (session);

    if (ret < 0)
    {
        fprintf (stderr, "*** Handshake failed\n");
        gnutls_perror (ret);
        goto end;
    }
    else
    {
        printf ("- Handshake was completed\n");
    }

    gnutls_record_send (session, MSG, strlen (MSG));

    ret = gnutls_record_recv (session, buffer, MAX_BUF);
    if (ret == 0)
    {
        printf ("- Peer has closed the TLS connection\n");
        goto end;
    }
    else if (ret < 0)
    {
        fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
        goto end;
    }

    printf ("- Received %d bytes: ", ret);
    for (ii = 0; ii < ret; ii++)
    {
        fputc (buffer[ii], stdout);
    }
    fputs ("\n", stdout);

    gnutls_bye (session, GNUTLS_SHUT_RDWR);

end:

    tcp_close (sd);

    gnutls_deinit (session);

    gnutls_certificate_free_credentials (xcred);
    gnutls_priority_deinit( priorities_cache);

    gnutls_global_deinit ();

    return 0;
}
예제 #30
0
static void start_daemon()
{
	// Capture USB device
	struct usb_sock_t *usb_sock = usb_open();
	if (usb_sock == NULL)
		goto cleanup_usb;

	// Capture a socket
	uint32_t desired_port = g_options.desired_port;
	struct tcp_sock_t *tcp_socket = tcp_open(desired_port);
	if (tcp_socket == NULL)
		goto cleanup_tcp;

	uint32_t real_port = tcp_port_number_get(tcp_socket);
	if (desired_port != 0 && desired_port != real_port) {
		ERR("Received port number did not match requested port number."
		    " The requested port number may be too high.");
		goto cleanup_tcp;
	}
	printf("%u\n", real_port);

	// Lose connection to caller
	if (!g_options.nofork_mode && fork() > 0)
		exit(0);

	for (;;) {
		struct service_thread_param *args = calloc(1, sizeof(*args));
		if (args == NULL) {
			ERR("Failed to alloc space for thread args");
			goto cleanup_thread;
		}

		args->usb_sock = usb_sock;
		args->tcp = tcp_conn_accept(tcp_socket);
		if (args->tcp == NULL) {
			ERR("Failed to open tcp connection");
			goto cleanup_thread;
		}

		int status = pthread_create(&args->thread_handle, NULL,
		                            &service_connection, args);
		if (status) {
			ERR("Failed to spawn thread, error %d", status);
			goto cleanup_thread;
		}

		continue;

	cleanup_thread:
		if (args != NULL) {
			if (args->tcp != NULL)
				tcp_conn_close(args->tcp);
			free(args);
		}
		break;
	}

cleanup_tcp:
	if (tcp_socket!= NULL)
		tcp_close(tcp_socket);
cleanup_usb:
	if (usb_sock != NULL)
		usb_close(usb_sock);
	return;
}