Skip to content

Instantly share code, notes, and snippets.

@rajibchy
Last active August 19, 2022 07:40
Show Gist options
  • Select an option

  • Save rajibchy/24dd2579d7e795a48738518f49d24f57 to your computer and use it in GitHub Desktop.

Select an option

Save rajibchy/24dd2579d7e795a48738518f49d24f57 to your computer and use it in GitHub Desktop.
C++ Socket Utility 💯 🌹
/**
* 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
/**
* 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