1 /*
2 * TCPProtoSocketAgent.cpp
3 *
4 */
5
6 #include "nsTCPProtoSocketAgent.h"
7
8 /////////////////////////////////////////////////////////////////////////
9 // NsProtoSimAgent::UdpSocketAgent implementation
10 //
11 static class ProtoSocketTcpAgentClass : public TclClass {
12 public:
ProtoSocketTcpAgentClass()13 ProtoSocketTcpAgentClass() : TclClass("Agent/ProtoSocket/TCP") {}
create(int,const char * const *)14 TclObject* create(int, const char*const*) {
15 return (new NsTCPProtoSocketAgent());
16 }
17 } class_proto_socket_tcp_agent;
18
NsTCPProtoSocketAgent()19 NsTCPProtoSocketAgent::NsTCPProtoSocketAgent()
20 : Agent(PT_TCP)
21 {
22 socketType_=NotInitialised;
23 outputNotification=false; // by default
24 // printf("NsTCPProtoSocketAgent: Created ok\n");
25 //SetDebugLevel(7);
26 }
27
Listen(UINT16 thePort)28 bool NsTCPProtoSocketAgent::Listen(UINT16 thePort) {
29 if (socketType_==NotInitialised) { // must be a server socket, port is set from the NsProtoSimAgent bind operation
30
31 PLOG(PL_DEBUG, "TCPProtoSocketAgent: Listening on %i\n", thePort);
32
33 Agent* simAgent = dynamic_cast<Agent*>(proto_socket->GetNotifier());
34
35 serverSocket = TCPSocketFactory::createServerSocketAgent(simAgent);
36
37 if (serverSocket==NULL) return FALSE;
38
39 serverSocket->setTCPAgentProtocol(TCPSocketAgent::FULLTCP);
40
41 serverSocket->bind(thePort);
42 socketType_=TcpServerSocket;
43
44 // printf("TCPProtoSocketAgent: Calling listen on server socket\n");
45
46 isOpen=true;
47
48 // start listening for connections
49 serverSocket->listen();
50
51 serverSocket->setListener(this);
52
53
54 // printf("TCPProtoSocketAgent: Server initialsed and listening\n");
55
56 }
57 else {
58 return false;
59 }
60
61 return true;
62 }
63
64 /**
65 *
66 * Enables the output notification for a socket i.e. whether SEND events are generated in trigger mode.
67 */
SetOutputNotification(bool outputnotify)68 bool NsTCPProtoSocketAgent::SetOutputNotification(bool outputnotify) {
69 outputNotification=outputnotify;
70 if (socketType_==TcpSocket)
71 tcpPipe->setOutputNotification(outputnotify);
72 return outputnotify;
73 }
74
Connect(const ProtoAddress & theAddress)75 bool NsTCPProtoSocketAgent::Connect(const ProtoAddress& theAddress) {
76 PLOG(PL_DEBUG, "TCPProtoSocketAgent: Connect Entering\n");
77
78 if (socketType_==NotInitialised) { // must be a client socket, port is set from the NsProtoSimAgent bind operation
79 PLOG(PL_DETAIL, "TCPProtoSocketAgent: Creating a new socket on %i, port %i\n", addr(), port());
80 Agent* simAgent = dynamic_cast<Agent*>(proto_socket->GetNotifier());
81 tcpPipe = TCPSocketFactory::createSocketAgent(simAgent); // sets simAgent as agent to bind to
82 if (tcpPipe==NULL) return FALSE;
83 tcpPipe->setTCPAgentProtocol(TCPSocketAgent::FULLTCP);
84
85 tcpPipe->bind(port());
86 tcpPipe->setListener(this); // notifications sent here
87
88 socketType_=TcpSocket;
89 isOpen=true;
90
91 PLOG(PL_DETAIL, "TCPProtoSocketAgent: Conencting now to address %u, port %i\n", theAddress.SimGetAddress(), theAddress.GetPort());
92 // connect to server
93
94 tcpPipe->setOutputNotification(outputNotification);
95 tcpPipe->connect(theAddress.SimGetAddress(), theAddress.GetPort());
96 }
97 else {
98 return false;
99 }
100
101 return true;
102 }
103
104 /**
105 * Here, we create a new protosocket to
106 * deal with the new connection and tell this TCPProtoSocketAgent to reply to the requesting
107 * client. This allows us to spwan off new agents to deal with multiple clients.
108 * NOTE that this assumes that the user provides a socket to deal with the connection !
109 */
Accept(ProtoSocket * theSocket)110 bool NsTCPProtoSocketAgent::Accept(ProtoSocket* theSocket) {
111 PLOG(PL_DEBUG, "TCPProtoSocketAgent::Accept Entering \n");
112
113 if (socketType_==NotInitialised) return FALSE;
114
115 theSocket->SetNotifier(proto_socket->GetNotifier());
116
117 // Note that the first argument does not matter because the third is false i.e. bindOnCreate is false
118 // so port is not used in Open
119 theSocket->Open(0, ProtoAddress::SIM, FALSE); //creates a new nsTCPProtoSocketAgent
120
121 NsTCPProtoSocketAgent *theProtoSocket = (NsTCPProtoSocketAgent *) static_cast<ProtoSimAgent::SocketProxy*>(theSocket->GetHandle());
122
123 TCPSocketAgent* socket = serverSocket->accept(); // create new socket agent for this connection
124
125 socket->setListener(theProtoSocket); // set the listener for RECEIVE events to this class
126
127 theProtoSocket->setTCPSocketAgent(socket); // set the socket agent in the new TCPProtoSocketAgent to be
128
129 // Need to set the destination...
130
131 ProtoAddress destination;
132 destination.SimSetAddress(socket->getDestinationAddress());
133 destination.SetPort(socket->getDestinationPort());
134 theSocket->SetDestination(destination);
135
136 PLOG(PL_DEBUG, "TCPProtoSocketAgent::Accept Exiting \n");
137
138 return true;
139 }
140
141
SendTo(const char * buffer,unsigned int & numBytes,const ProtoAddress & dstAddr)142 bool NsTCPProtoSocketAgent::SendTo(const char* buffer, unsigned int& numBytes, const ProtoAddress& dstAddr) {
143 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Sending Data\n");
144
145 if (socketType_==NotInitialised) return FALSE;
146
147 unsigned int bytesSent = tcpPipe->send(numBytes,buffer);
148 numBytes=bytesSent;
149 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Completed send\n");
150 return true;
151 }
152
153
154 /**
155 * Catches events thrown from the underlying TCP agents.
156 */
tcpEventReceived(TCPEvent * event)157 bool NsTCPProtoSocketAgent::tcpEventReceived(TCPEvent *event) {
158
159 // check how these map ...
160
161 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Getting Callback\n");
162
163 if (event->getType()==TCPEvent::ACCEPT)
164 {
165 if (proto_socket)
166 proto_socket->OnNotify(ProtoSocket::NOTIFY_INPUT);
167 }
168 else if (event->getType()==TCPEvent::CONNECTED)
169 {
170 // printf("Connected event in ProtoSocketAgent\n");
171 if (proto_socket)
172 proto_socket->OnNotify(ProtoSocket::NOTIFY_OUTPUT);
173
174 }
175 else if (event->getType()==TCPEvent::SEND)
176 {
177 if (proto_socket)
178 proto_socket->OnNotify(ProtoSocket::NOTIFY_OUTPUT);
179 }
180 else if (event->getType()==TCPEvent::RECEIVE)
181 {
182
183 recv_data = (char *)event->getData();
184 recv_data_len = event->getDataSize();
185 recv_data_offset=0; // reset offset to 0
186
187 PLOG(PL_DEBUG,"NsTCPProtoSocketAgent::tcpEventReceived: Got data of length %i\n", recv_data_len);
188 PLOG(PL_DETAIL, "NsTCPProtoSocketAgent::tcpEventReceived: Destination port and Address are %i and %i\n", tcpPipe->getDestinationPort(),
189 tcpPipe->getDestinationAddress());
190
191 src_addr.SimSetAddress(tcpPipe->getDestinationAddress());
192 src_addr.SetPort(tcpPipe->getDestinationPort());
193
194 PLOG(PL_DETAIL, "NsTCPProtoSocketAgent::tcpEventReceived event being sent to socket ...\n ");
195
196 if (proto_socket)
197 proto_socket->OnNotify(ProtoSocket::NOTIFY_INPUT);
198 PLOG(PL_DETAIL, "NsTCPProtoSocketAgent::tcpEventReceived event processed ... \n");
199
200 }
201 else if (event->getType()==TCPEvent::DISCONNECTED)
202 {
203 if (proto_socket)
204 proto_socket->OnNotify(ProtoSocket::NOTIFY_NONE);
205 }
206 else
207 {
208 PLOG(PL_ERROR, "NsTCPProtoSocketAgent::tcpEventReceived UNKNOWN Event on node %i\n", addr());
209 return false;
210 }
211
212 PLOG(PL_DEBUG, "NsTCPProtoSocketAgent::tcpEventReceived finished Callback\n");
213
214 delete event;
215 return true;
216 }
217
218 /**
219 * Close and detach the relevant agents from the sockets that have been created by this
220 * NS TCP Proto Sokcet Agent. This agent is NOT attached but others it communicates with are...
221 */
Shutdown()222 bool NsTCPProtoSocketAgent::Shutdown() {
223 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Shutdown\n");
224
225 if (!isOpen) return false;
226
227 if (socketType_==NotInitialised) return TRUE;
228
229 if (socketType_==TcpSocket)
230 tcpPipe->shutdown();
231 else
232 serverSocket->shutdown();
233
234 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Socket shutdown initiated\n");
235
236 return true;
237 } // end NsProtoSimAgent::UdpSocketAgent::Close()
238
239
240 /**
241 * Close and detach the relevant agents from the sockets that have been created by this
242 * NS TCP Proto Sokcet Agent. This agent is NOT attached but others it communicates with are...
243 */
Close()244 bool NsTCPProtoSocketAgent::Close() {
245 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Closing\n");
246 bool state=false;
247 if (!isOpen) return true;
248
249 if (socketType_==NotInitialised) return TRUE; // is closed already
250
251 if (socketType_==TcpSocket)
252 state=tcpPipe->closeSocket();
253 else
254 state=serverSocket->closeSocket();
255
256 PLOG(PL_DEBUG, "NsTCPPrototSocketAgent: Socket Closed\n");
257
258 isOpen=false;
259
260 return state;
261 } // end NsProtoSimAgent::UdpSocketAgent::Close()
262
263