Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Build

on:
push:
branches: [master, feature/**]
pull_request:
branches: [master]
workflow_dispatch:

permissions:
contents: read

jobs:
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6

- name: Configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release

- name: Build
run: cmake --build build --config Release

- name: Upload workflow artifact
uses: actions/upload-artifact@v7
with:
name: psn-macos-release
path: build/examples/psn_*
if-no-files-found: error
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
*.log
examples/vs2015/bin/
examples/vs2015/build/
.vs/
.vs/
build
23 changes: 23 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.10)
project(PSN VERSION 2.03 LANGUAGES CXX)

# Set C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Create header-only library interface
add_library(psn INTERFACE)

# Add include directory
target_include_directories(psn INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

# Platform-specific settings for network library
if(WIN32)
target_link_libraries(psn INTERFACE ws2_32)
endif()

# Add examples
add_subdirectory(examples)
40 changes: 40 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# PSN Examples CMakeLists.txt

# psn_server executable
add_executable(psn_server
vs2015/psn_server/psn_server.cpp
)

target_link_libraries(psn_server PRIVATE psn)

# psn_client executable
add_executable(psn_client
vs2015/psn_client/psn_client.cpp
)

target_link_libraries(psn_client PRIVATE psn)

# psn_glut_client executable (optional - requires GLUT and OpenGL)
find_package(OpenGL)
find_package(GLUT)

if(OpenGL_FOUND AND GLUT_FOUND)
add_executable(psn_glut_client
vs2015/psn_glut_client/psn_glut_client.cpp
)

target_link_libraries(psn_glut_client PRIVATE psn OpenGL::GL GLUT::GLUT)
target_include_directories(psn_glut_client PRIVATE ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR})

# macOS specific: no need to copy DLL files
# Windows would need post-build copy for glut32.dll or glut64.dll

message(STATUS "Building psn_glut_client (OpenGL visualizer)")
else()
if(NOT OpenGL_FOUND)
message(WARNING "OpenGL not found - skipping psn_glut_client")
endif()
if(NOT GLUT_FOUND)
message(WARNING "GLUT not found - skipping psn_glut_client")
endif()
endif()
18 changes: 13 additions & 5 deletions examples/vs2015/psn_client/psn_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@

#include <iostream>

void main( void )
// Platform-specific sleep function
#ifdef _WIN32
#define SLEEP_MS(ms) Sleep(ms)
#else
#include <unistd.h>
#define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

int main( void )
{
wsa_session session ;

Expand All @@ -46,9 +54,9 @@ void main( void )

//====================================================
// Main loop
while ( 1 )
while ( 1 )
{
Sleep( 1 ) ;
SLEEP_MS( 1 ) ;

// Update Client
::std::string msg ;
Expand Down Expand Up @@ -114,6 +122,6 @@ void main( void )
}
}
}
}


return 0 ;
}
23 changes: 19 additions & 4 deletions examples/vs2015/psn_glut_client/psn_glut_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,24 @@
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
// Platform-specific sleep function
#ifdef _WIN32
#define SLEEP_MS(ms) Sleep(ms)
#else
#include <unistd.h>
#define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

// Platform-specific OpenGL headers
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#endif

#define PI_DEF 3.1415926535897932384626433832795f

Expand Down Expand Up @@ -261,7 +276,7 @@ idle( void )
::std::cout << "\n-----------------------------------------------" << ::std::endl ;
}

Sleep( 10 ) ;
SLEEP_MS( 10 ) ;

// schedule GL update
glutPostRedisplay() ;
Expand Down
16 changes: 13 additions & 3 deletions examples/vs2015/psn_server/psn_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@
#include <list>
#include <string>

void main( void )
// Platform-specific sleep function
#ifdef _WIN32
#define SLEEP_MS(ms) Sleep(ms)
#else
#include <unistd.h>
#define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

int main( void )
{
wsa_session session ;

Expand Down Expand Up @@ -120,7 +128,9 @@ void main( void )
::std::cout << "-----------------------------------------------" << ::std::endl ;
}

Sleep( 1 ) ;
timestamp++ ;
SLEEP_MS( 1 ) ;
timestamp++ ;
}

return 0 ;
}
63 changes: 37 additions & 26 deletions include/utils/udp_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ THE SOFTWARE.
#ifndef UDP_SOCKET_H
#define UDP_SOCKET_H

// Platform detection - include appropriate implementation
#ifdef _WIN32

// Windows implementation
#include <WinSock2.h>
#include <Ws2tcpip.h>

#pragma message("Note: including lib: Ws2_32.lib")
#pragma message("Note: including lib: Ws2_32.lib")
#pragma comment(lib, "Ws2_32.lib")

#include <string>
Expand All @@ -49,7 +53,7 @@ class wsa_session
WSACleanup() ;
}

private :
private :

WSAData data_ ;
} ;
Expand All @@ -59,7 +63,7 @@ class udp_socket
{
public :

udp_socket( void )
udp_socket( void )
{
// UDP socket
socket_ = socket( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;
Expand All @@ -69,7 +73,7 @@ class udp_socket
ioctlsocket( socket_ , FIONBIO , &arg ) ;
}

~udp_socket( void )
~udp_socket( void )
{
closesocket( socket_ ) ;
}
Expand All @@ -80,7 +84,7 @@ class udp_socket
add.sin_family = AF_INET ;
InetPton( AF_INET , address.c_str() , &add.sin_addr.s_addr ) ;
add.sin_port = htons( port ) ;

if ( sendto( socket_ , message.c_str() , (int)message.length() , 0 , reinterpret_cast<SOCKADDR *>( &add ) , sizeof( add ) ) > 0 )
return true ;

Expand Down Expand Up @@ -117,52 +121,59 @@ class udp_socket
return false ;
}

bool enable_send_message_multicast( void )
bool enable_send_message_multicast( void )
{
struct in_addr add ;
add.s_addr = INADDR_ANY ;

int result = setsockopt( socket_ ,
IPPROTO_IP ,
IP_MULTICAST_IF ,
(const char*)&add ,
int result = setsockopt( socket_ ,
IPPROTO_IP ,
IP_MULTICAST_IF ,
(const char*)&add ,
sizeof( add ) ) ;
return ( result != SOCKET_ERROR ) ;
return ( result != SOCKET_ERROR ) ;
}

bool join_multicast_group( const ::std::string & ip_group )
bool join_multicast_group( const ::std::string & ip_group )
{
struct ip_mreq imr;
struct ip_mreq imr;

InetPton( AF_INET , ip_group.c_str() , &imr.imr_multiaddr.s_addr ) ;
imr.imr_interface.s_addr = INADDR_ANY ;

int result = setsockopt( socket_ ,
IPPROTO_IP ,
IP_ADD_MEMBERSHIP ,
(char*) &imr ,
int result = setsockopt( socket_ ,
IPPROTO_IP ,
IP_ADD_MEMBERSHIP ,
(char*) &imr ,
sizeof(struct ip_mreq) ) ;
return ( result != SOCKET_ERROR ) ;
return ( result != SOCKET_ERROR ) ;
}

bool leave_multicast_group( const ::std::string & ip_group )
bool leave_multicast_group( const ::std::string & ip_group )
{
struct ip_mreq imr;

InetPton( AF_INET , ip_group.c_str() , &imr.imr_multiaddr.s_addr ) ;
imr.imr_interface.s_addr = INADDR_ANY ;

int result = setsockopt( socket_ ,
IPPROTO_IP ,
int result = setsockopt( socket_ ,
IPPROTO_IP ,
IP_DROP_MEMBERSHIP ,
(char*) &imr ,
(char*) &imr ,
sizeof(struct ip_mreq) ) ;
return ( result != SOCKET_ERROR ) ;
return ( result != SOCKET_ERROR ) ;
}

private :

SOCKET socket_ ;
SOCKET socket_ ;
} ;

#else

// POSIX implementation (macOS, Linux, etc.)
#include "udp_socket_posix.h"

#endif

#endif
Loading