--- /dev/null
+/*
+ * "Copyright (c) 2008, 2009 The Regents of the University of California.
+ * All rights reserved."
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+#ifndef TCPLIB_H_
+#define TCPLIB_H_
+
+/*
+ * tcplib: a simple tcp implemented in a library
+ * @author Stephen Dawson-Haggerty <stevedh@eecs.berkeley.edu>
+ *
+ *
+ */
+
+// #include <netinet/in.h>
+#include "ip.h"
+
+#define min(X,Y) (((X) > (Y)) ? (Y) : (X))
+#ifndef PC
+#define printf(X, args ...) dbg("stdout", X, ## args)
+#define fprintf(X, Y, args ...) dbg("fprintf", Y, ## args)
+#endif
+
+typedef enum {
+ TCP_CLOSED = 0,
+ TCP_LISTEN,
+ TCP_SYN_RCVD,
+ TCP_SYN_SENT,
+ TCP_ESTABLISHED,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_FIN_WAIT_1,
+ TCP_FIN_WAIT_2,
+ TCP_CLOSING,
+ TCP_TIME_WAIT,
+} tcplib_sock_state_t;
+
+enum {
+ TCP_ACKPENDING = 0x3,
+ TCP_DUPACKS = 0x3c,
+ TCP_DUPACKS_OFF = 2,
+ TCP_ACKSENT = 0x80,
+};
+
+enum {
+ /* how many timer tics to stay in TIME_WAIT */
+ TCPLIB_TIMEWAIT_LEN = 1,
+ TCPLIB_2MSL = 4,
+ /* how many un-acked retransmissions before we give up the connection */
+ TCPLIB_GIVEUP = 6,
+};
+
+#define GET_ACK_COUNT(X) (((X) & TCP_DUPACKS) >> TCP_DUPACKS_OFF)
+#define UNSET_ACK_COUNT(X) ((X) &= ~TCP_DUPACKS)
+#define INCR_ACK_COUNT(X) ((X) += 1 << TCP_DUPACKS_OFF)
+
+struct tcplib_sock {
+ uint8_t flags;
+
+ /* local and remote endpoints */
+ struct sockaddr_in6 l_ep;
+ struct sockaddr_in6 r_ep;
+
+ /* current connection state */
+ tcplib_sock_state_t state;
+
+ void *tx_buf;
+ uint16_t tx_buf_len;
+
+ /* max segment size, or default if
+ we didn't bother to pull it out
+ of the options field */
+ uint16_t mss;
+
+ uint16_t my_wind;
+ /* the window the other end is
+ reporting */
+ uint16_t r_wind;
+ uint16_t cwnd;
+ uint16_t ssthresh;
+
+ // the current next sequence number for ourgoing data.
+ uint32_t seqno;
+ // and the index of the last byte we've ACKed
+ uint32_t ackno;
+
+ struct {
+ int8_t retx;
+ } timer;
+
+ /* retransmission counter */
+ uint16_t retxcnt;
+
+ /* callbacks for this connection */
+/* struct { */
+/* /\* a previous connection request has finished *\/ */
+/* void (*connect_done)(struct tcplib_sock *sock, int error); */
+
+/* /\* a callback to signal new data is ready *\/ */
+/* void (*recvfrom)(struct tcplib_sock *sock, void *data, int len); */
+
+/* /\* the connection was closed by the other party *\/ */
+/* void (*closed)(struct tcplib_sock *sock); */
+
+/* /\* you called close(); we've finished closing the socket. *\/ */
+/* void (*close_done)(struct tcplib_sock *sock); */
+/* } ops; */
+
+ /* this needs to be at the end so
+ we can call init() on a socket
+ without blowing away the linked
+ list */
+ struct tcplib_sock *next;
+};
+
+/* EVENTS
+ * ------------------------------------------------------------
+ *
+ * calls generated by tcplib that must be dealt with elsewhere in the
+ * program.
+ */
+
+
+/* called when a new connection request is recieved on a socket which
+ * is LISTENing.
+ *
+ *
+ * return 0 if it wants to accept the connection and allocated a
+ * buffer for it; -1 otherwise.
+ */
+struct tcplib_sock *tcplib_accept(struct tcplib_sock *conn,
+ struct sockaddr_in6 *from);
+
+/* a call-out point for tcplib to send a message */
+void tcplib_send_out(struct split_ip_msg *msg, struct tcp_hdr *tcph);
+
+/* upcall for new data; may be dispatched all the way out to a
+ * handler.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise. The error may be safely ignored.
+ */
+int tcplib_process(struct ip6_hdr *ip_packet, void *payload);
+
+/*
+ * should be called every 500ms to increment all the tcp timers
+ */
+int tcplib_timer_process();
+
+/* Just fill in the fields of the socket.
+ *
+ * If you perform a send on a socket in this state, an ephemeral port
+ * will be allocated to it.
+ *
+ * This must be called once on any socket that might be sent on, or
+ * might have bind() called.
+ */
+int tcplib_init_sock(struct tcplib_sock *sock);
+
+/* bind the socket to a local address */
+int tcplib_bind(struct tcplib_sock *sock,
+ struct sockaddr_in6 *addr);
+
+/* connect the socket to a remote endpoint */
+int tcplib_connect(struct tcplib_sock *sock,
+ struct sockaddr_in6 *serv_addr);
+
+
+/* send data on an open socket.
+ *
+ * returns: 0 on success
+ * other errors
+ * - no local buffer is available,
+ *
+ */
+int tcplib_send(struct tcplib_sock *sock,
+ void *data, int len);
+
+int tcplib_close(struct tcplib_sock *sock);
+
+/* abort a connection
+ *
+ * This will send a RST segment if the connection has been opened and
+ * immediately return the socket to the CLOSED, uninitialized state,
+ * although buffer pointers are maintained.
+ *
+ */
+int tcplib_abort(struct tcplib_sock *sock);
+#endif