Last active
August 19, 2022 07:40
-
-
Save rajibchy/24dd2579d7e795a48738518f49d24f57 to your computer and use it in GitHub Desktop.
C++ Socket Utility 💯 🌹
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Copyright (c) 2022, https://github.com/rajibchy All rights reserved. | |
| * Copyrights licensed under the New BSD License. | |
| * See the accompanying LICENSE file for terms. | |
| */ | |
| // 11:29 AM 11/28/2021 | |
| // by Rajib Chy | |
| #ifdef _MSC_VER | |
| #define _WINSOCK_DEPRECATED_NO_WARNINGS | |
| #include <Winsock2.h> | |
| #pragma warning(push) | |
| #pragma warning( disable :4311 4302 ) | |
| #endif //_MSC_VER | |
| #include "utility.h" | |
| namespace sow_utility { | |
| void buff_write( char* payload, const std::string& str, int offset, size_t count ) { | |
| size_t len = str.size( ); | |
| for ( size_t i = 0; i < count; i++ ) { | |
| if ( i >= len ) { | |
| payload[offset] = 0x20; | |
| } else { | |
| payload[offset] = str[i]; | |
| } | |
| offset++; | |
| } | |
| } | |
| void buff_write_int( char* payload, const std::string& str, int offset, size_t count ) { | |
| size_t len = str.size( ); | |
| for ( size_t i = 0; i < count; i++ ) { | |
| if ( i >= len ) { | |
| payload[offset] = 0x20; | |
| } else { | |
| payload[offset] = ( int )str[i]; | |
| } | |
| offset++; | |
| } | |
| } | |
| void write_uint16be( char* data, uint16_t value, int offset ) { | |
| data[offset] = ( uint8_t )(value >> 8); offset++; | |
| data[offset] = ( uint8_t )value; | |
| } | |
| uint16_t read_uint16be( char* data, int offset ) { | |
| uint16_t ret = 0; | |
| ret |= data[offset] << 8; offset++; | |
| ret |= data[offset]; | |
| return ret; | |
| } | |
| bool socket_is_valid( int socket ) { | |
| if ( socket == 0 )return false; | |
| #ifdef _MSC_VER | |
| return socket != INVALID_SOCKET; | |
| #else | |
| return socket >= 0; | |
| #endif | |
| } | |
| void socket_invalidate( int& socket ) { | |
| #ifdef _MSC_VER | |
| socket = (int)INVALID_SOCKET; | |
| #else | |
| socket = -1; | |
| #endif | |
| } | |
| //------------------------- | |
| // Set the socket I/O mode: In this case FIONBIO | |
| // enables or disables the blocking mode for the | |
| // socket based on the numerical value of iMode. | |
| // If iMode = 0, blocking is enabled; | |
| // If iMode != 0, non-blocking mode is enabled. | |
| // https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-ioctlsocket | |
| bool socket_fionread( int s, int& bytes ) { | |
| bytes = 0; | |
| #if defined(_MSC_VER) | |
| return ::ioctlsocket( s, FIONREAD, &(( unsigned long& )bytes) ) == 0; | |
| #elif defined(USING_STREAMS) | |
| return ::ioctl( s, I_NREAD, &bytes ) >= 0; | |
| #else | |
| return ::ioctl( s, FIONREAD, &bytes ) == 0; | |
| #endif | |
| } | |
| int socket_recv( int s, char* buf, int length ) { | |
| return ::recv( s, buf, length, 0 ); | |
| } | |
| int socket_setsockopt( int s, int opt, int optval ) { | |
| int level = SOL_SOCKET; | |
| if ( opt == TCP_NODELAY ) | |
| level = IPPROTO_TCP; | |
| #ifdef _MSC_VER | |
| return ::setsockopt( s, level, opt, | |
| ( char* )&optval, sizeof( optval ) ); | |
| #else | |
| return ::setsockopt( s, level, opt, | |
| &optval, sizeof( optval ) ); | |
| #endif | |
| } | |
| int socket_getsockopt( int s, int opt, int& optval ) { | |
| int level = SOL_SOCKET; | |
| if ( opt == TCP_NODELAY ) | |
| level = IPPROTO_TCP; | |
| #ifdef _MSC_VER | |
| int length = sizeof( int ); | |
| #else | |
| socklen_t length = sizeof( socklen_t ); | |
| #endif | |
| return ::getsockopt( s, level, opt, ( char* )&optval, &length ); | |
| } | |
| int socket_send( int s, const char* msg, int length ) { | |
| return ::send( s, msg, length, 0 ); | |
| } | |
| bool socket_disconnected( int s ) { | |
| char byte; | |
| return ::recv( s, &byte, sizeof( byte ), MSG_PEEK ) <= 0; | |
| } | |
| int socket_create_connector( ) { | |
| return (int)::socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); | |
| } | |
| int socket_connect( int socket, const char* ip, unsigned short int port ) { | |
| sockaddr_in addr; | |
| //memset( &addr, 0, sizeof( addr ) ); | |
| addr.sin_addr.s_addr = inet_addr( ip ); | |
| addr.sin_family = AF_INET; | |
| addr.sin_port = htons( port ); | |
| int result = ::connect( | |
| socket, reinterpret_cast< sockaddr* >(&addr), | |
| sizeof( addr ) | |
| ); | |
| return result; | |
| } | |
| int socket_init( ) { | |
| #if defined(_MSC_VER) | |
| WORD version = MAKEWORD( 2, 2 ); | |
| WSADATA data; | |
| int t = ::WSAStartup( version, &data ); | |
| return t; | |
| #else | |
| struct sigaction sa; | |
| sa.sa_handler = SIG_IGN; | |
| sigemptyset( &sa.sa_mask ); | |
| sa.sa_flags = 0; | |
| sigaction( SIGPIPE, &sa, 0 ); | |
| #endif | |
| } | |
| void socket_term( ) { | |
| #ifdef _MSC_VER | |
| WSACleanup( ); | |
| #endif | |
| } | |
| int socket_can_readable( int sock, struct fd_set fds ) { | |
| struct timeval timeout = { 1, 0 }; | |
| fd_set readfds = fds; | |
| // Wait for input (1 second timeout) | |
| if ( select( 1 + sock, &readfds, 0, 0, &timeout ) <= 0 ) return FALSE; | |
| return TRUE; | |
| } | |
| int socket_can_writeable( int sock, struct fd_set fds ) { | |
| struct timeval timeout = { 0, 0 }; | |
| fd_set writefds = fds; | |
| if ( select( 1 + sock, 0, &writefds, 0, &timeout ) <= 0 ) return FALSE; | |
| return TRUE; | |
| } | |
| void socket_close( int s ) { | |
| printf( "shutting down socket -> %d\n", s ); | |
| // see more https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-shutdown | |
| int result = 0;//::shutdown( s, SD_BOTH ); | |
| #ifdef _MSC_VER | |
| if ( result == SOCKET_ERROR ) { | |
| printf( "shutdown failed: %d\n", WSAGetLastError( ) ); | |
| closesocket( s ); | |
| } else { | |
| ::closesocket( s ); | |
| } | |
| #else | |
| ::close( s ); | |
| #endif | |
| } | |
| #ifndef _MSC_VER | |
| bool socket_is_bad( int s ) { | |
| struct stat buf; | |
| fstat( s, &buf ); | |
| return errno == EBADF; | |
| } | |
| #endif | |
| void process_sleep( double s ) { | |
| #ifdef _MSC_VER | |
| Sleep( ( long )(s * 1000) ); | |
| #else | |
| timespec time, remainder; | |
| double intpart; | |
| time.tv_nsec = ( long )(modf( s, &intpart ) * 1e9); | |
| time.tv_sec = ( int )intpart; | |
| while ( nanosleep( &time, &remainder ) == -1 ) | |
| time = remainder; | |
| #endif | |
| } | |
| // thread | |
| bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ) { | |
| #ifdef _MSC_VER | |
| thread_id result = 0; | |
| unsigned int id = 0; | |
| result = _beginthreadex( NULL, 0, func, var, 0, &id ); | |
| if ( result == 0 ) return false; | |
| #else | |
| thread_id result = 0; | |
| if ( pthread_create( &result, 0, func, var ) != 0 ) return false; | |
| #endif | |
| thread = result; | |
| return true; | |
| } | |
| bool thread_spawn( THREAD_START_ROUTINE func, void* var ) { | |
| thread_id thread = 0; | |
| return thread_spawn( func, var, thread ); | |
| } | |
| void thread_join( thread_id thread ) { | |
| #ifdef _MSC_VER | |
| WaitForSingleObject( ( void* )thread, INFINITE ); | |
| CloseHandle( ( HANDLE )thread ); | |
| #else | |
| pthread_join( ( pthread_t )thread, 0 ); | |
| #endif | |
| } | |
| void thread_detach( thread_id thread ) { | |
| #ifdef _MSC_VER | |
| CloseHandle( ( HANDLE )thread ); | |
| #else | |
| pthread_t t = thread; | |
| pthread_detach( t ); | |
| #endif | |
| } | |
| thread_id thread_self( ) { | |
| #ifdef _MSC_VER | |
| return ( unsigned )GetCurrentThread( ); | |
| #else | |
| return pthread_self( ); | |
| #endif | |
| } | |
| } | |
| #ifdef _MSC_VER | |
| #pragma warning(pop) | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Copyright (c) 2022, https://github.com/rajibchy All rights reserved. | |
| * Copyrights licensed under the New BSD License. | |
| * See the accompanying LICENSE file for terms. | |
| */ | |
| // 11:29 AM 11/28/2021 | |
| // by Rajib Chy | |
| #ifdef _MSC_VER | |
| #pragma once | |
| #pragma warning(push) | |
| #pragma warning( disable :4309 4311 4302 4503 4355 4786 4267 4244 4018 5040 4101 ) | |
| #endif//_MSC_VER | |
| #if !defined(_sow_utility_h) | |
| #define _sow_utility_h | |
| #if defined(_MSC_VER) | |
| #define _WINSOCK_DEPRECATED_NO_WARNINGS | |
| #include <WinSock2.h> | |
| #include <WS2tcpip.h> | |
| #include <process.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #pragma comment (lib, "Ws2_32.lib") | |
| #pragma comment (lib, "Mswsock.lib") | |
| #pragma comment (lib, "AdvApi32.lib") | |
| #else | |
| #error "Not implemented" | |
| #endif //_WIN32 | |
| #include <string> | |
| #include <iostream> | |
| #include <climits> | |
| #define ALLOCATOR std::allocator | |
| typedef int socklen_t; | |
| #if(_MSC_VER >= 1900) | |
| typedef _beginthreadex_proc_type THREAD_START_ROUTINE; | |
| #define THREAD_PROC unsigned int _stdcall | |
| #elif(_MSC_VER > 0) | |
| typedef unsigned int( _stdcall* THREAD_START_ROUTINE )(void*); | |
| #define THREAD_PROC unsigned int _stdcall | |
| #else | |
| extern "C" { typedef void* ( THREAD_START_ROUTINE )(void*); } | |
| #define THREAD_PROC void * | |
| #endif | |
| #ifdef _MSC_VER | |
| // typedef unsigned thread_id; | |
| typedef uintptr_t thread_id; | |
| #else | |
| typedef pthread_t thread_id; | |
| #endif | |
| namespace sow_utility { | |
| //static const std::string _null_string( "NullString\0" ); | |
| // [help] | |
| uint16_t read_uint16be( char* data, int offset ); | |
| void write_uint16be( char* data, uint16_t value, int offset ); | |
| void buff_write( char* payload, const std::string& str, int offset, size_t count ); | |
| void buff_write_int( char* payload, const std::string& str, int offset, size_t count ); | |
| // [/help] | |
| int socket_init( ); | |
| void socket_term( ); | |
| void socket_close( int s ); | |
| int socket_create_connector( ); | |
| bool socket_disconnected( int s ); | |
| bool socket_is_valid( int socket ); | |
| void socket_invalidate( int& socket ); | |
| bool socket_fionread( int s, int& bytes ); | |
| int socket_recv( int s, char* buf, int length ); | |
| int socket_setsockopt( int s, int opt, int optval ); | |
| int socket_getsockopt( int s, int opt, int& optval ); | |
| int socket_send( int s, const char* msg, int length ); | |
| int socket_can_readable( int sock, struct fd_set fds ); | |
| int socket_can_writeable( int sock, struct fd_set fds ); | |
| int socket_connect( int socket, const char* ip, unsigned short int port ); | |
| #if !defined(_MSC_VER) | |
| bool socket_is_bad( int s ); | |
| #endif // !_MSC_VER | |
| void process_sleep( double s ); | |
| thread_id thread_self( ); | |
| void thread_join( thread_id thread ); | |
| void thread_detach( thread_id thread ); | |
| bool thread_spawn( THREAD_START_ROUTINE func, void* var ); | |
| bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ); | |
| } | |
| #endif //!_sow_utility_h | |
| #ifdef _MSC_VER | |
| #pragma warning(pop) | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment