1 : //=============================================================================
2 : // File <$/src/cpp/prod/com/SocketCom.cpp>
3 : // This file is part of YaOrb : Yet Another Object Request Broker,
4 : // Copyright (c) 2000-2003, Marc Alff.
5 : //
6 : // This program is free software; you can redistribute it and/or
7 : // modify it under the terms of the GNU General Public License
8 : // as published by the Free Software Foundation; either version 2
9 : // of the License, or (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program; if not, write to the Free Software
18 : // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 : //
20 : //=============================================================================
21 :
22 : // Portability
23 : #include "yaorb/config.h"
24 : #include "src/cpp/prod/port/port_stdc.h"
25 : #include "src/cpp/prod/port/port_socket.h"
26 : #include "src/cpp/prod/port/port_unistd.h"
27 :
28 : #include <sys/types.h>
29 : #include <sys/un.h>
30 :
31 : #include <yaorb/CORBA.h>
32 :
33 : #include "src/cpp/prod/com/buffer.h"
34 : #include "src/cpp/prod/com/SocketCom.h"
35 : #include "src/cpp/prod/sync/Spin.h"
36 : #include "src/cpp/prod/protocol/giop/message_header.h"
37 : #include "src/cpp/prod/protocol/cdr/cdr_memory.h"
38 : #include "src/cpp/prod/tool/Assert.h"
39 : #include "src/cpp/prod/tool/Error.h"
40 : #include "src/cpp/prod/tool/String.h"
41 : #include "src/cpp/prod/tool/DEVELOPMENT.h"
42 :
43 4 : SocketCom::SocketCom(const String & host, int port)
44 : : Com(),
45 4 : _soc(0)
46 : {
47 : int rc ;
48 :
49 : #ifdef LATER
50 : _soc = socket(AF_INET, SOCK_STREAM, 0) ;
51 :
52 : struct sockaddr_in server ;
53 : server.sin_family = AF_INET ;
54 : server.sin_port = port ;
55 : server.sin_addr.s_addr = ... ;
56 : #else
57 4 : NON_DEV("Using UNIX sockets instead of INET") ;
58 : char buff[80] ;
59 4 : sprintf(buff, "/tmp/port%d", port) ;
60 :
61 4 : _soc = socket(AF_LOCAL, SOCK_STREAM, 0) ;
62 :
63 : struct sockaddr_un server ;
64 4 : server.sun_family = AF_LOCAL ;
65 4 : strcpy(server.sun_path, buff);
66 : #endif
67 :
68 4 : if (_soc <0)
69 : {
70 0 : PERROR("socket failed") ;
71 0 : NON_DEV("handle error") ;
72 : }
73 :
74 4 : rc = connect(_soc, (const struct sockaddr*) & server, sizeof(server)) ;
75 :
76 4 : if (rc != 0)
77 : {
78 2 : PERROR("connect failed") ;
79 2 : fprintf(stderr, "Failed to connect soc %d to port %d\n", _soc, port) ;
80 2 : NON_DEV("handle error") ;
81 : }
82 0 : }
83 :
84 2 : SocketCom::SocketCom(int soc)
85 2 : : _soc(soc)
86 : {
87 : }
88 :
89 2 : SocketCom::~SocketCom()
90 : {
91 2 : }
92 :
93 : void
94 4 : SocketCom::ReadBuffer(Buffer & buf)
95 : {
96 : int cr ;
97 : CORBA::Octet *returnData = NULL ;
98 : CORBA::Octet *tmpdata = NULL ;
99 : int tmpsize ;
100 : int readSize ;
101 : int msgSize ;
102 : int returnSize ;
103 :
104 : //**************************************************************************
105 4 : BEGIN_OBJECT_WIDE_CRITICAL_SECTION(_receiveSpin)
106 : {
107 : // CRITICAL :
108 : // 1st recv just reads enought data to decode a GIOP header,
109 : // 2nd recv read the rest of the GIOP message,
110 : // so the socket is better left untouched between the two recv calls
111 :
112 : //-----------------------------------------------------------------------
113 : // First, read a GIOP Header (12 bytes).
114 : //-----------------------------------------------------------------------
115 :
116 : int headersize = GIOP_MESSAGE_HEADER_SIZE ;
117 : CORBA::Octet headerdata[GIOP_MESSAGE_HEADER_SIZE] ;
118 :
119 : readSize = headersize ;
120 : tmpdata = headerdata ;
121 :
122 2 : while (readSize > 0)
123 : {
124 4 : cr = recv(_soc, tmpdata, readSize, MSG_NOSIGNAL) ;
125 4 : if (cr>0)
126 : {
127 2 : tmpdata += cr ;
128 2 : readSize -= cr ;
129 : }
130 : else
131 : {
132 : // FIXME : Possible Deny Of Service attack
133 :
134 2 : PERROR("recv failed") ;
135 :
136 2 : PermanentFailure() ;
137 :
138 2 : CORBA::COMM_FAILURE ex ;
139 2 : ex.completed(CORBA::COMPLETED_NO) ;
140 2 : ex._raise() ;
141 : }
142 : }
143 :
144 : //------------------------------------------------------------------------
145 : // Decode the message header.
146 : //------------------------------------------------------------------------
147 :
148 2 : GIOPMessageHeader hdr ;
149 2 : CDRMemory cdrs(headerdata, headersize, YAORB::CDR_READ) ;
150 :
151 2 : hdr.cdr(& cdrs) ;
152 :
153 2 : msgSize = hdr.GetMessageSize() ;
154 :
155 : //------------------------------------------------------------------------
156 : // Reallocate some space for the complete message if necessary
157 : //------------------------------------------------------------------------
158 :
159 2 : returnSize = GIOP_MESSAGE_HEADER_SIZE + msgSize ;
160 :
161 2 : tmpsize = buf.GetSize() ;
162 :
163 2 : if (tmpsize < returnSize)
164 : {
165 0 : buf.resize(returnSize) ;
166 : }
167 :
168 2 : returnData = buf.GetData() ;
169 :
170 : //------------------------------------------------------------------------
171 : // save the GIOP header in the buffer.
172 : //------------------------------------------------------------------------
173 :
174 2 : memcpy(returnData, headerdata, headersize) ;
175 :
176 : //------------------------------------------------------------------------
177 : // Read the rest of the GIOP message.
178 : //------------------------------------------------------------------------
179 :
180 : readSize = msgSize ;
181 2 : tmpdata = returnData + headersize ;
182 :
183 4 : while (readSize >0)
184 : {
185 2 : cr = recv(_soc, tmpdata, readSize, MSG_NOSIGNAL) ;
186 2 : if (cr >0)
187 : {
188 2 : tmpdata += cr ;
189 2 : readSize -= cr ;
190 : }
191 : else
192 : {
193 : // FIXME : Possible Deny Of Service attack
194 :
195 0 : PERROR("recv failed") ;
196 :
197 0 : PermanentFailure() ;
198 :
199 0 : CORBA::COMM_FAILURE ex ;
200 0 : ex.completed(CORBA::COMPLETED_NO) ;
201 0 : ex._raise() ;
202 : }
203 0 : }
204 2 : }
205 : END_OBJECT_WIDE_CRITICAL_SECTION
206 : //**************************************************************************
207 :
208 : return ;
209 : }
210 :
211 6 : void SocketCom::WriteBuffer(const Buffer& buf)
212 : {
213 : int cr ;
214 6 : int size = buf.GetSize() ;
215 6 : CORBA::Octet* data = buf.GetData() ;
216 :
217 : CORBA::Octet *writeData = data ;
218 : int writeSize = size ;
219 :
220 : //**************************************************************************
221 6 : BEGIN_OBJECT_WIDE_CRITICAL_SECTION(_sendSpin)
222 : {
223 8 : while (writeSize > 0)
224 : {
225 6 : cr = send(_soc, data, size, MSG_NOSIGNAL) ;
226 6 : if (cr > 0)
227 : {
228 : writeData += cr ;
229 2 : writeSize -= cr ;
230 : }
231 : else
232 : {
233 4 : PERROR("send failed") ;
234 :
235 4 : PermanentFailure() ;
236 :
237 4 : CORBA::COMM_FAILURE ex ;
238 4 : ex.completed(CORBA::COMPLETED_MAYBE) ;
239 4 : ex._raise() ;
240 : }
241 : }
242 4 : }
243 : END_OBJECT_WIDE_CRITICAL_SECTION
244 : //**************************************************************************
245 :
246 : return ;
247 : }
248 :
249 12 : int SocketCom::GetSocket() const
250 : {
251 : return _soc ;
252 : }
253 :
254 : void
255 2 : SocketCom::Close(void)
256 : {
257 2 : close(_soc) ;
258 : }
259 :
|