• R/O
  • SSH
  • HTTPS

tidesnet: Commit


Commit MetaInfo

Revisão69 (tree)
Hora2020-01-29 08:26:16
Autorquiret

Mensagem de Log

- added support for AF_UNIX style sockets for both Windows and Linux

Mudança Sumário

Diff

--- library/include/tidesnet/netsocket.h (revision 68)
+++ library/include/tidesnet/netsocket.h (revision 69)
@@ -140,7 +140,7 @@
140140 // Available protocol types.
141141 enum class eConnProtocol
142142 {
143- UDP,
143+ UDP, // not really a "connection-based" type, lol. but you can create a socket to send data to!
144144 TCP
145145 };
146146
@@ -148,7 +148,8 @@
148148 enum class eConnFamily
149149 {
150150 IPV4,
151- IPV6
151+ IPV6,
152+ UNIX
152153 };
153154
154155 enum eReceiveFlag : std::uint32_t
--- library/include/tidesnet/tidesnet.h (revision 68)
+++ library/include/tidesnet/tidesnet.h (revision 69)
@@ -73,8 +73,10 @@
7373
7474 // Typical networking API.
7575 ConnReceiver* CreateNetListener( std::uint16_t port, eConnFamily connFamily, eConnProtocol protoType );
76+ ConnReceiver* CreateNetListener( const char *portPath, eConnFamily connFamily, eConnProtocol protoType );
7677 NetSocket* ConnectRemoteIPV4( const ipdescIPV4& server, std::uint16_t port, eConnProtocol protoType );
7778 NetSocket* ConnectRemoteIPV6( const ipdescIPV6& server, std::uint16_t port, eConnProtocol protoType );
79+ NetSocket* ConnectLocalPath( const char *portPath, eConnProtocol protoType );
7880
7981 // Resource termination.
8082 void DestroyNetListener( ConnReceiver *recv );
--- library/src/main.cpp (revision 68)
+++ library/src/main.cpp (revision 69)
@@ -127,17 +127,8 @@
127127 nativeNetMan->memMan = memMan;
128128 }
129129
130-ConnReceiver* TidesNet::CreateNetListener( std::uint16_t port, eConnFamily connFamily, eConnProtocol protoType )
130+ConnReceiver* _connReceiver_fromNativeData( TidesNetImpl *nativeNetMan, connReceiverNativeData&& nativeData )
131131 {
132- TidesNetImpl *nativeNetMan = (TidesNetImpl*)this;
133-
134- connReceiverNativeData nativeData;
135-
136- if ( _connReceiver_createNative( port, connFamily, protoType, nativeData ) == false )
137- {
138- return nullptr;
139- }
140-
141132 // Construct our runtime type.
142133 tides_net_fact_allocator mem_alloc( nativeNetMan->memMan );
143134
@@ -162,6 +153,40 @@
162153 return netReceiver;
163154 }
164155
156+ConnReceiver* TidesNet::CreateNetListener( std::uint16_t port, eConnFamily connFamily, eConnProtocol protoType )
157+{
158+ TidesNetImpl *nativeNetMan = (TidesNetImpl*)this;
159+
160+ connReceiverNativeData nativeData;
161+
162+ if ( _connReceiver_createNative( port, connFamily, protoType, nativeData ) == false )
163+ {
164+ return nullptr;
165+ }
166+
167+ return _connReceiver_fromNativeData( nativeNetMan, std::move( nativeData ) );
168+}
169+
170+ConnReceiver* TidesNet::CreateNetListener( const char *portPath, eConnFamily connFamily, eConnProtocol protoType )
171+{
172+ // This method currently only works for the "unix-style" sockets.
173+ if ( connFamily != eConnFamily::UNIX )
174+ {
175+ return nullptr;
176+ }
177+
178+ TidesNetImpl *nativeNetMan = (TidesNetImpl*)this;
179+
180+ connReceiverNativeData nativeData;
181+
182+ if ( _connReceiver_createNativeNamed( portPath, connFamily, protoType, nativeData ) == false )
183+ {
184+ return nullptr;
185+ }
186+
187+ return _connReceiver_fromNativeData( nativeNetMan, std::move( nativeData ) );
188+}
189+
165190 NetSocket* TidesNet::ConnectRemoteIPV4( const ipdescIPV4& server, std::uint16_t port, eConnProtocol protoType )
166191 {
167192 // Since we offer a robust interface of a few controlled net addressings (IPV4 and IPV6), we are
@@ -171,7 +196,7 @@
171196
172197 #ifdef _WIN32
173198 // Create the system network resource.
174- int addressFamily;
199+ short addressFamily;
175200 SOCKET sysSocket = create_system_socket( eConnFamily::IPV4, protoType, addressFamily );
176201
177202 if ( sysSocket == INVALID_SOCKET )
@@ -253,7 +278,7 @@
253278
254279 #ifdef _WIN32
255280 // Create the system network resource.
256- int addressFamily;
281+ short addressFamily;
257282 SOCKET sysSocket = create_system_socket( eConnFamily::IPV6, protoType, addressFamily );
258283
259284 if ( sysSocket == INVALID_SOCKET )
@@ -331,6 +356,75 @@
331356 return netSock;
332357 }
333358
359+NetSocket* TidesNet::ConnectLocalPath( const char *portPath, eConnProtocol protoType )
360+{
361+ TidesNetImpl *nativeNetMan = (TidesNetImpl*)this;
362+
363+#ifdef _WIN32
364+ short addressFamily;
365+ SOCKET sysSocket = create_system_socket( eConnFamily::UNIX, protoType, addressFamily );
366+
367+ tides_sockaddr_un sockaddr;
368+ sockaddr.family = addressFamily;
369+ strncpy( sockaddr.local_path, portPath, countof(sockaddr.local_path) );
370+
371+ int conn_err = connect( sysSocket, (const struct sockaddr*)&sockaddr, sizeof(sockaddr) );
372+
373+ if ( conn_err != 0 )
374+ {
375+ closesocket( sysSocket );
376+ return nullptr;
377+ }
378+#elif defined(__linux__)
379+ std::uint16_t addressFamily;
380+ int socketFD = create_system_socket( eConnFamily::UNIX, protoType, addressFamily );
381+
382+ tides_sockaddr_un sockaddr;
383+ sockaddr.family = addressFamily;
384+ strncpy( sockaddr.local_path, portPath, countof(sockaddr.local_path)-1 );
385+ sockaddr.local_path[ countof(sockaddr.local_path)-1 ] = 0;
386+
387+ int conn_err = connect( socketFD, (const struct sockaddr*)&sockaddr, sizeof(sockaddr) );
388+
389+ if ( conn_err != 0 )
390+ {
391+ _linux_socket_close( socketFD );
392+ return nullptr;
393+ }
394+#else
395+#error Missing TidesNet::ConnectLocalPath socket creation implementation
396+#endif //CROSS PLATFORM CODE.
397+
398+ // Try to create our runtime container and store the system stuff inside.
399+ tides_net_fact_allocator memAlloc( nativeNetMan->memMan );
400+
401+ NetSocketImpl *netSock = eir::dyn_new_struct <NetSocketImpl> (
402+ memAlloc, nullptr, nativeNetMan,
403+#ifdef _WIN32
404+ std::move( sysSocket )
405+#elif defined(__linux__)
406+ std::move( socketFD )
407+#else
408+#error Missing TidesNet::ConnectLocalPath runtime argument implementation
409+#endif //CROSS PLATFORM CODE
410+ );
411+
412+ if ( netSock == nullptr )
413+ {
414+#ifdef _WIN32
415+ closesocket( sysSocket );
416+#elif defined(__linux__)
417+ _linux_socket_close( socketFD );
418+#else
419+#error Missing TidesNet::ConnectLocalPath cleanup on error implementation
420+#endif //CROSS PLATFORM CODE
421+ return nullptr;
422+ }
423+
424+ // We are fine.
425+ return netSock;
426+}
427+
334428 void TidesNet::DestroyNetListener( ConnReceiver *netListener )
335429 {
336430 TidesNetImpl *nativeNetMan = (TidesNetImpl*)this;
--- library/src/netsocket.impl.hxx (revision 68)
+++ library/src/netsocket.impl.hxx (revision 69)
@@ -17,13 +17,17 @@
1717 #ifdef _WIN32
1818
1919 // Some methods for the Windows environment.
20-inline SOCKET create_system_socket( eConnFamily connFamily, eConnProtocol protoType, int& addressFamilyOut )
20+inline SOCKET create_system_socket( eConnFamily connFamily, eConnProtocol protoType, short& addressFamilyOut )
2121 {
2222 // Translate the provided protocol family to Windows-speak.
23- int addressFamily = 0;
23+ short addressFamily = 0;
2424
2525 switch( connFamily )
2626 {
27+ case eConnFamily::UNIX:
28+ // Might not be supported on every Windows computer.
29+ addressFamily = AF_UNIX;
30+ break;
2731 case eConnFamily::IPV4:
2832 addressFamily = AF_INET;
2933 break;
@@ -42,11 +46,27 @@
4246 {
4347 case eConnProtocol::TCP:
4448 type = SOCK_STREAM;
45- protocol = IPPROTO_TCP;
49+
50+ if ( connFamily == eConnFamily::UNIX )
51+ {
52+ protocol = 0;
53+ }
54+ else
55+ {
56+ protocol = IPPROTO_TCP;
57+ }
4658 break;
4759 case eConnProtocol::UDP:
4860 type = SOCK_DGRAM;
49- protocol = IPPROTO_UDP;
61+
62+ if ( connFamily == eConnFamily::UNIX )
63+ {
64+ protocol = 0;
65+ }
66+ else
67+ {
68+ protocol = IPPROTO_UDP;
69+ }
5070 break;
5171 default:
5272 return INVALID_SOCKET;
@@ -80,9 +100,32 @@
80100 SOCKET socketHandle;
81101 };
82102
103+inline bool _connReceiver_setupSocket( SOCKET sysSocket )
104+{
105+ // Also give it some backlog.
106+ int backlogConfigError = listen( sysSocket, SOMAXCONN );
107+
108+ if ( backlogConfigError != 0 )
109+ {
110+#ifdef _DEBUG
111+ int sockErr = WSAGetLastError();
112+#endif //_DEBUG
113+
114+ return false;
115+ }
116+
117+ return true;
118+}
119+
83120 inline bool _connReceiver_createNative( std::uint16_t port, eConnFamily connFamily, eConnProtocol protoType, connReceiverNativeData& dataOut )
84121 {
85- int addressFamily;
122+ // This method only works for IP-address based connection families.
123+ if ( connFamily != eConnFamily::IPV4 && connFamily != eConnFamily::IPV6 )
124+ {
125+ return false;
126+ }
127+
128+ short addressFamily;
86129 SOCKET sysSocket = create_system_socket( connFamily, protoType, addressFamily );
87130
88131 if ( sysSocket == INVALID_SOCKET )
@@ -121,10 +164,7 @@
121164 return false;
122165 }
123166
124- // Also give it some backlog.
125- int backlogConfigError = listen( sysSocket, SOMAXCONN );
126-
127- if ( backlogConfigError != 0 )
167+ if ( _connReceiver_setupSocket( sysSocket ) == false )
128168 {
129169 // Error out.
130170 closesocket( sysSocket );
@@ -136,6 +176,68 @@
136176 return true;
137177 }
138178
179+inline bool _connReceiver_createNativeNamed( const char *portPath, eConnFamily connFamily, eConnProtocol protoType, connReceiverNativeData& dataOut )
180+{
181+ // Does only work for UNIX as of now.
182+ if ( connFamily != eConnFamily::UNIX )
183+ {
184+ return false;
185+ }
186+
187+ // Make sure the name is available. If it is not then try making it available.
188+ {
189+ BOOL delSuccess = DeleteFileA( portPath );
190+
191+ if ( delSuccess == FALSE )
192+ {
193+ DWORD delError = GetLastError();
194+
195+ if ( delError != ERROR_FILE_NOT_FOUND )
196+ {
197+ return false;
198+ }
199+ }
200+ }
201+
202+ short addressFamily;
203+ SOCKET sysSocket = create_system_socket( connFamily, protoType, addressFamily );
204+
205+ if ( sysSocket == INVALID_SOCKET )
206+ {
207+ return false;
208+ }
209+
210+ bool hasBindSucceeded = false;
211+
212+ if ( connFamily == eConnFamily::UNIX )
213+ {
214+ tides_sockaddr_un sockaddr;
215+ sockaddr.family = addressFamily;
216+ strncpy( sockaddr.local_path, portPath, countof(sockaddr.local_path) );
217+
218+ hasBindSucceeded = ( bind( sysSocket, (const struct sockaddr*)&sockaddr, sizeof(sockaddr) ) == 0 );
219+ }
220+
221+ if ( hasBindSucceeded == false )
222+ {
223+#ifdef _DEBUG
224+ int sockErr = WSAGetLastError();
225+#endif //_DEBUG
226+
227+ closesocket( sysSocket );
228+ return false;
229+ }
230+
231+ if ( _connReceiver_setupSocket( sysSocket ) == false )
232+ {
233+ closesocket( sysSocket );
234+ return false;
235+ }
236+
237+ dataOut.socketHandle = sysSocket;
238+ return true;
239+}
240+
139241 inline void _connReceiver_cleanupNative( connReceiverNativeData&& data )
140242 {
141243 closesocket( data.socketHandle );
@@ -149,10 +251,14 @@
149251 inline int create_system_socket( eConnFamily connFamily, eConnProtocol protoType, std::uint16_t& addressFamilyOut )
150252 {
151253 // First convert our parameters to the platform representation.
152- int addressFamily = 0;
254+ std::uint16_t addressFamily = 0;
153255
154256 switch( connFamily )
155257 {
258+ case eConnFamily::UNIX:
259+ // Available on every relevant Linux version, I guess.
260+ addressFamily = AF_UNIX;
261+ break;
156262 case eConnFamily::IPV4:
157263 addressFamily = AF_INET;
158264 break;
@@ -171,11 +277,27 @@
171277 {
172278 case eConnProtocol::TCP:
173279 type = SOCK_STREAM;
174- protocol = IPPROTO_TCP;
280+
281+ if ( connFamily == eConnFamily::UNIX )
282+ {
283+ protocol = 0;
284+ }
285+ else
286+ {
287+ protocol = IPPROTO_TCP;
288+ }
175289 break;
176290 case eConnProtocol::UDP:
177291 type = SOCK_DGRAM;
178- protocol = IPPROTO_UDP;
292+
293+ if ( connFamily == eConnFamily::UNIX )
294+ {
295+ protocol = 0;
296+ }
297+ else
298+ {
299+ protocol = IPPROTO_UDP;
300+ }
179301 break;
180302 default:
181303 return -1;
@@ -189,6 +311,7 @@
189311 }
190312
191313 // Assign properties.
314+ if ( connFamily != eConnFamily::UNIX )
192315 {
193316 linger info;
194317 info.l_onoff = 1;
@@ -209,8 +332,26 @@
209332 int socketFD;
210333 };
211334
335+inline bool _connReceiver_setupSocket( int socketFD )
336+{
337+ int backlogConfigError = listen( socketFD, SOMAXCONN );
338+
339+ if ( backlogConfigError != 0 )
340+ {
341+ return false;
342+ }
343+
344+ return true;
345+}
346+
212347 inline bool _connReceiver_createNative( std::uint16_t port, eConnFamily connFamily, eConnProtocol protoType, connReceiverNativeData& dataOut )
213348 {
349+ // Only supported for IP-based protocols.
350+ if ( connFamily != eConnFamily::IPV4 && connFamily != eConnFamily::IPV6 )
351+ {
352+ return false;
353+ }
354+
214355 std::uint16_t addressFamily;
215356 int socketFD = create_system_socket( connFamily, protoType, addressFamily );
216357
@@ -248,9 +389,7 @@
248389 return false;
249390 }
250391
251- int backlogConfigError = listen( socketFD, SOMAXCONN );
252-
253- if ( backlogConfigError != 0 )
392+ if ( _connReceiver_setupSocket( socketFD ) == false )
254393 {
255394 _linux_socket_close( socketFD );
256395 return false;
@@ -261,6 +400,62 @@
261400 return true;
262401 }
263402
403+inline bool _connReceiver_createNativeNamed( const char *portName, eConnFamily connFamily, eConnProtocol protoType, connReceiverNativeData& dataOut )
404+{
405+ // Only AF_UNIX for now.
406+ if ( connFamily != eConnFamily::UNIX )
407+ {
408+ return false;
409+ }
410+
411+ // Make sure the socket is available.
412+ if ( access( portName, F_OK ) == 0 )
413+ {
414+ int unlink_err = unlink( portName );
415+
416+ if ( unlink_err != 0 )
417+ {
418+ return false;
419+ }
420+ }
421+
422+ std::uint16_t addressFamily;
423+ int socketFD = create_system_socket( connFamily, protoType, addressFamily );
424+
425+ if ( socketFD < 0 )
426+ {
427+ return false;
428+ }
429+
430+ bool hasBindSucceeded = false;
431+
432+ if ( connFamily == eConnFamily::UNIX )
433+ {
434+ tides_sockaddr_un sockaddr;
435+ sockaddr.family = addressFamily;
436+ strncpy( sockaddr.local_path, portName, countof(sockaddr.local_path)-1 );
437+ sockaddr.local_path[ countof(sockaddr.local_path)-1 ] = 0;
438+
439+ hasBindSucceeded = ( bind( socketFD, (const struct sockaddr*)&sockaddr, sizeof(sockaddr) ) == 0 );
440+ }
441+
442+ if ( hasBindSucceeded == false )
443+ {
444+ _linux_socket_close( socketFD );
445+ return false;
446+ }
447+
448+ if ( _connReceiver_setupSocket( socketFD ) == false )
449+ {
450+ _linux_socket_close( socketFD );
451+ return false;
452+ }
453+
454+ // Simply return it.
455+ dataOut.socketFD = socketFD;
456+ return true;
457+}
458+
264459 inline void _connReceiver_cleanupNative( connReceiverNativeData&& data )
265460 {
266461 _linux_socket_close( data.socketFD );
--- library/src/tidesdef.hxx (revision 68)
+++ library/src/tidesdef.hxx (revision 69)
@@ -36,6 +36,12 @@
3636 ipdescIPV6 in_addr;
3737 endian::big_endian <unsigned long> scope_id; // set to 0 for remote connections
3838 };
39+
40+// For details on AF_UNIX in Windows see: https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows/
41+struct tides_sockaddr_un : public tides_sockaddr_in_head
42+{
43+ char local_path[108];
44+};
3945 #elif defined(__linux__)
4046 struct tides_sockaddr_in_head
4147 {
@@ -57,6 +63,12 @@
5763 ipdescIPV6 in_addr;
5864 endian::big_endian <std::uint32_t> scope_id;
5965 };
66+
67+// http://man7.org/linux/man-pages/man7/unix.7.html
68+struct tides_sockaddr_un : public tides_sockaddr_in_head
69+{
70+ char local_path[108];
71+};
6072 #endif //CROSS PLATFORM CODE
6173
6274 _NS_END_TIDESNET
Show on old repository browser