📄 tcp_usrreq.pc
字号:
/* * GloMoSim is COPYRIGHTED software. Release 2.02 of GloMoSim is available * at no cost to educational users only. * * Commercial use of this software requires a separate license. No cost, * evaluation licenses are available for such purposes; please contact * info@scalable-networks.com * * By obtaining copies of this and any other files that comprise GloMoSim2.02, * you, the Licensee, agree to abide by the following conditions and * understandings with respect to the copyrighted software: * * 1.Permission to use, copy, and modify this software and its documentation * for education and non-commercial research purposes only is hereby granted * to Licensee, provided that the copyright notice, the original author's * names and unit identification, and this permission notice appear on all * such copies, and that no charge be made for such copies. Any entity * desiring permission to use this software for any commercial or * non-educational research purposes should contact: * * Professor Rajive Bagrodia * University of California, Los Angeles * Department of Computer Science * Box 951596 * 3532 Boelter Hall * Los Angeles, CA 90095-1596 * rajive@cs.ucla.edu * * 2.NO REPRESENTATIONS ARE MADE ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY * PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * * 3.Neither the software developers, the Parallel Computing Lab, UCLA, or any * affiliate of the UC system shall be liable for any damages suffered by * Licensee from the use of this software. */// Use the latest version of Parsec if this line causes a compiler error./* * $Id: tcp_usrreq.pc,v 1.7 1999/09/28 05:25:39 ktang Exp $ * * Ported from FreeBSD 2.2.2. * This file contains TCP functions that process application requests. *//* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 * $Id: tcp_usrreq.pc,v 1.7 1999/09/28 05:25:39 ktang Exp $ */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "api.h"#include "main.h"#include "structmsg.h"#include "tcp.h"#include "transport.h"#include "in_pcb.h"#include "tcp_config.h"#include "tcp_fsm.h"#include "tcp_proto.h"#include "tcp_seq.h"#include "tcp_var.h"static struct tcpcb *tcp_usrclosed(GlomoNode *, struct tcpcb *, struct tcpstat *);/* * Prepare to accept connections. */void tcp_listen (GlomoNode *node, struct inpcb *phead, APP_TYPE app_type, NODE_ADDR local_addr, short local_port, int priority){ struct inpcb *inp; int result = 0; struct tcpcb *tp; Message *msg; TransportToAppListenResult *tcpListenResult; /* check whether this server already exists */ inp = (struct inpcb *) in_pcblookup(phead, local_addr, local_port, 0, 0, INPCB_WILDCARD); if (inp != phead) { result = -2; /* listen failed, server already set up */ } else { inp = tcp_attach(phead, app_type, local_addr, local_port, -1, -1, -1, priority); if (inp == NULL){ result = -1; /* listen failed */ } else { result = inp->con_id; /* listen succeeded */ tp = intotcpcb(inp); tp->t_state = TCPS_LISTEN; } } /* * report status to application * result = -2, server port already set up * result = -1, failed to set up the server port * result >= 0, succeeded */ msg = GLOMO_MsgAlloc(node, GLOMO_APP_LAYER, app_type, MSG_APP_FromTransListenResult); GLOMO_MsgInfoAlloc(node, msg, sizeof(TransportToAppListenResult)); tcpListenResult = (TransportToAppListenResult *) msg->info; tcpListenResult->localAddr = local_addr; tcpListenResult->localPort = local_port; tcpListenResult->connectionId = result; GLOMO_MsgSend(node, msg, TRANSPORT_DELAY); }/* * Do a send by putting data in output queue and * possibly send more data. */voidtcp_send(node, phead, conn_id, payload, length, tcp_now, tcp_stat) GlomoNode *node; struct inpcb *phead; int conn_id; unsigned char *payload; int length; unsigned long tcp_now; struct tcpstat *tcp_stat;{ struct inpcb *inp; struct tcpcb *tp; inp = in_pcbsearch(phead, conn_id); if (inp == phead) { /* * can't find the in_pcb of the connection */ fprintf(stderr, "TCP: can't find (id=%u,conn=%d)\n", node->nodeAddr, conn_id); assert(FALSE); } /* * put data in the send buffer of the connection * and call tcp_output to send data */ tp = intotcpcb(inp); length = append_buf(node, inp, payload, length); if (length > 0){ tcp_output(node, tp, tcp_now, tcp_stat); }}/* * Common subroutine to open a TCP connection to remote host specified * by remote_addr. * Initialize connection parameters and enter SYN-SENT state. */void tcp_connect(GlomoNode *node, struct inpcb *phead, APP_TYPE app_type, NODE_ADDR local_addr, short local_port, NODE_ADDR remote_addr, short remote_port, unsigned long tcp_now, tcp_seq *tcp_iss, struct tcpstat *tcp_stat, long unique_id, int priority){ struct inpcb *inp; int result = 0; struct tcpcb *tp; Message *msg; TransportToAppOpenResult *tcpOpenResult; /* check whether this connection already exists */ inp = (struct inpcb *) in_pcblookup(phead, local_addr, local_port, remote_addr, remote_port, INPCB_NO_WILDCARD); if (inp != phead) { /* connection already exists */ result = -1; } else { /* create inpcb and tcpcb for this connection */ inp = tcp_attach(phead, app_type, local_addr, local_port, remote_addr, remote_port, unique_id, priority); if (inp == NULL) { /* can't create inpcb and tcpcb */ result = -1; } else { tp = intotcpcb(inp); tp->t_template = (struct tcpiphdr *) tcp_template(tp); if (tp->t_template == 0) { /* can't allocate template */ pc_free(tp); inp->inp_ppcb = 0; in_pcbdetach(inp); result = -1; } } } if (result == -1) { /* * report failure to application and stop processing * this message */ msg = GLOMO_MsgAlloc(node, GLOMO_APP_LAYER, app_type, MSG_APP_FromTransOpenResult); GLOMO_MsgInfoAlloc(node, msg, sizeof(TransportToAppOpenResult)); tcpOpenResult = (TransportToAppOpenResult *) msg->info; tcpOpenResult->type = TCP_CONN_ACTIVE_OPEN; tcpOpenResult->localAddr = inp->inp_local_addr; tcpOpenResult->localPort = inp->inp_local_port; tcpOpenResult->remoteAddr = inp->inp_remote_addr; tcpOpenResult->remotePort = inp->inp_remote_port; tcpOpenResult->connectionId = result; tcpOpenResult->uniqueId = inp->unique_id; GLOMO_MsgSend(node, msg, TRANSPORT_DELAY); return; } /* * Set receiving window scale. * Enter SYN_SENT state. * Start keepalive timer and seed output sequence space. * Send initial segment on connection. */ while ((tp->request_r_scale < TCP_MAX_WINSHIFT) && ((TCP_MAXWIN << tp->request_r_scale) < inp->inp_rcv_hiwat)) tp->request_r_scale++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; if (tcp_stat) tcp_stat->tcps_connattempt++; tp->iss = *tcp_iss; *tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); tcp_output(node, tp, tcp_now, tcp_stat); inp->usrreq = INPCB_USRREQ_OPEN; }/* * Attach TCP protocol, allocating * internet protocol control block, tcp control block, * buffer space, initialize connection state to CLOSED. */struct inpcb *tcp_attach (struct inpcb *head, APP_TYPE app_type, NODE_ADDR local_addr, short local_port, NODE_ADDR remote_addr, short remote_port, long unique_id, int priority){ struct inpcb *inp; struct tcpcb *tp; /* * Create inpcb and fill in connection information */ if ((remote_addr == -1) && (remote_port == -1)) { /* pcb for listening port */ inp = in_pcballoc(head, 0, 0); } else { /* pcb for connections */ inp = in_pcballoc(head, TCP_SENDSPACE, TCP_RECVSPACE);; } if (inp == NULL) return (inp); inp->app_proto_type = app_type; inp->inp_local_addr = local_addr; inp->inp_local_port = local_port; inp->inp_remote_addr = remote_addr; inp->inp_remote_port = remote_port; inp->con_id = get_conid(head); inp->unique_id = unique_id; inp->priority = priority; /* create a tcpcb */ tp = tcp_newtcpcb(inp); if (tp == 0){ in_pcbdetach(inp); return (NULL); } tp->t_state = TCPS_CLOSED; return (inp);}/* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * Otherwise, switch states based on user close, and * send segment to peer (with FIN). */voidtcp_disconnect(node, phead, conn_id, tcp_now, tcp_stat) GlomoNode *node; struct inpcb *phead; int conn_id; unsigned long tcp_now; struct tcpstat *tcp_stat;{ struct inpcb *inp; struct tcpcb *tp; inp = in_pcbsearch(phead, conn_id); if (inp == phead) { /* * can't find the in_pcb of the connection */ fprintf(stderr, "TCP: can't find (id=%ld,conn=%d)\n", node->nodeAddr, conn_id); assert(FALSE); } inp->usrreq = INPCB_USRREQ_CLOSE; tp = intotcpcb(inp); if (tp->t_state < TCPS_ESTABLISHED) tp = tcp_close(node, tp, tcp_stat); else { tp = tcp_usrclosed(node, tp, tcp_stat); if (tp) tcp_output(node, tp, tcp_now, tcp_stat); }}/* * User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer, * and just have to play tedious game waiting * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */static struct tcpcb *tcp_usrclosed(node, tp, tcp_stat) GlomoNode *node; struct tcpcb *tp; struct tcpstat *tcp_stat;{ switch (tp->t_state) { case TCPS_CLOSED: case TCPS_LISTEN: tp->t_state = TCPS_CLOSED; tp = tcp_close(node, tp, tcp_stat); break; case TCPS_SYN_SENT: case TCPS_SYN_RECEIVED: tp->t_flags |= TF_NEEDFIN; break; case TCPS_ESTABLISHED: tp->t_state = TCPS_FIN_WAIT_1; break; case TCPS_CLOSE_WAIT: tp->t_state = TCPS_LAST_ACK; break; } if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { /* To prevent the connection hanging in FIN_WAIT_2 forever. */ if (tp->t_state == TCPS_FIN_WAIT_2) tp->t_timer[TCPT_2MSL] = TCPTV_MAXIDLE; } return (tp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -