2727
2828#define DEFAULT_PORT 1100
2929
30- DWORD WINAPI ServerThread (LPVOID lpParam);
31- bool CheckIfPortAvailable (short int dwPort);
32-
3330#define BUFFER_LENGTH (MAX_WIDTH * MAX_HEIGHT * 3 )
3431
35- SOCKET server_socket = INVALID_SOCKET;
36- long bufferlength;
3732byte* framePointer;
3833byte frameBuffer[BUFFER_LENGTH];
3934
35+ #ifdef TCP_SERVER
36+ DWORD WINAPI ServerThread (LPVOID lpParam);
37+ bool CheckIfPortAvailable (short int dwPort);
38+
39+ SOCKET server_socket = INVALID_SOCKET;
40+ #endif // TCP_SERVER
41+
42+ struct TCPClientInfo
43+ {
44+ TCPClientInfo () {
45+ client_socket = INVALID_SOCKET;
46+ addressinfo = NULL ;
47+ }
48+ TCPClientInfo (SOCKET socket_, struct addrinfo * addressinfo_) {
49+ client_socket = socket_;
50+ addressinfo = addressinfo_;
51+ }
52+ SOCKET client_socket;
53+ struct addrinfo * addressinfo = NULL ;
54+ };
55+
56+ #ifdef TCP_CLIENT
57+ DWORD WINAPI ClientThread (LPVOID lpParam);
58+
59+ SOCKET client_socket = INVALID_SOCKET;
60+ TCPClientInfo client_info;
61+ #endif // TCP_CLIENT
4062
4163#pragma region CVCam
4264// ////////////////////////////////////////////////////////////////////////
@@ -50,7 +72,7 @@ CUnknown * WINAPI CVCam::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
5072}
5173
5274CVCam::CVCam (LPUNKNOWN lpunk, HRESULT *phr) :
53- CSource(NAME(" Virtual TCP Cam" ), lpunk, CLSID_VirtualCam)
75+ CSource(NAME(" Virtual TCP Cam" ), lpunk, CLSID_VirtualCam) // Source name
5476{
5577 // DbgLog((LOG_TRACE, 0, TEXT("Creating camera object"))); // not working somehow
5678 // DbgOutString("Hello World"); // Compile error
@@ -59,7 +81,7 @@ CVCam::CVCam(LPUNKNOWN lpunk, HRESULT *phr) :
5981 CAutoLock cAutoLock (&m_cStateLock);
6082 // Create the one and only output pin
6183 m_paStreams = (CSourceStream **) new CVCamStream*[1 ];
62- stream = new CVCamStream (phr, this , L" Virtual Video" );
84+ stream = new CVCamStream (phr, this , L" Virtual Video" ); // Pinname
6385 m_paStreams[0 ] = stream;
6486}
6587
@@ -84,14 +106,24 @@ CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) :
84106 // Set the default media type as 1920x1080 30Hz
85107 GetMediaType (0 , &m_mt);
86108
109+ #ifdef TCP_SERVER
87110 // DbgLog((LOG_CUSTOM1, 1, TEXT("Starting server")));
88111 SetupServer ();
89112 // DbgLog((LOG_TRACE, 3, TEXT("test string")));
113+ #endif
114+ #ifdef TCP_CLIENT
115+ SetupClient ();
116+ #endif
90117}
91118
92119CVCamStream::~CVCamStream ()
93120{
121+ #ifdef TCP_SERVER
94122 CleanupServer ();
123+ #endif
124+ #ifdef TCP_CLIENT
125+ CleanupClient ();
126+ #endif
95127}
96128
97129HRESULT CVCamStream::QueryInterface (REFIID riid, void **ppv)
@@ -455,13 +487,11 @@ HRESULT CVCamStream::QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *
455487//
456488// ////////////////////////////////////////////////////////////////////////
457489#pragma region TCP Server
490+ #ifdef TCP_SERVER
458491
459492int CVCamStream::SetupServer () {
460-
461- bufferlength = sizeof (frameBuffer);
462493 framePointer = &frameBuffer[0 ];
463494
464-
465495 WSADATA wsaData;
466496 int iResult;
467497
@@ -564,90 +594,49 @@ DWORD WINAPI ServerThread(LPVOID lpParam)
564594 SOCKADDR_STORAGE from;
565595 char servstr[NI_MAXSERV],
566596 hoststr[NI_MAXHOST];
567- int socket_type,
568- retval,
597+ int retval,
569598 fromlen,
570599 bytecount;
571600
572601 // Retrieve the socket handle
573602 server_socket_handle = (SOCKET)lpParam;
574603
575- // Get the socket type back
576- fromlen = sizeof (socket_type);
577- retval = getsockopt (server_socket_handle, SOL_SOCKET, SO_TYPE, (char *)&socket_type, &fromlen);
578- if (retval == INVALID_SOCKET)
579- {
580- fprintf (stderr, " getsockopt(SO_TYPE) failed: %d\n " , WSAGetLastError ());
581- goto cleanup;
582- }
583-
584- for (;;)
585- {
586- fromlen = sizeof (from);
587-
588- if (socket_type == SOCK_STREAM)
589- {
590- if (client_socket != INVALID_SOCKET)
591- {
592- //
593- // If we have a client connection recv and send until done
594- //
595- bytecount = recv (client_socket, (char *)frameBuffer, BUFFER_LENGTH, 0 );
596- if (bytecount == SOCKET_ERROR)
597- {
598- fprintf (stderr, " recv failed: %d\n " , WSAGetLastError ());
599- goto cleanup;
600- }
601- else if (bytecount == 0 )
602- {
603- // Client connection was closed
604- retval = shutdown (client_socket, SD_SEND);
605- if (retval == SOCKET_ERROR)
606- {
607- fprintf (stderr, " shutdown failed: %d\n " , WSAGetLastError ());
608- goto cleanup;
609- }
610-
611- closesocket (client_socket);
612- client_socket = INVALID_SOCKET;
613- }
604+ for (;;) {
605+ if (client_socket != INVALID_SOCKET) {
606+ //
607+ // If we have a client connection recv and send until done
608+ //
609+ bytecount = recv (client_socket, (char *)frameBuffer, BUFFER_LENGTH, 0 );
610+ if (bytecount == SOCKET_ERROR) {
611+ fprintf (stderr, " recv failed: %d\n " , WSAGetLastError ());
612+ closesocket (client_socket);
613+ client_socket = INVALID_SOCKET;
614614 }
615- else
616- {
617- //
618- // No client connection so wait for one
619- //
620- client_socket = accept (server_socket_handle, (SOCKADDR*)&from, &fromlen);
621- if (client_socket == INVALID_SOCKET)
622- {
623- fprintf (stderr, " accept failed: %d\n " , WSAGetLastError ());
624- goto cleanup;
615+ else if (bytecount == 0 ) {
616+ // Client connection was closed
617+ retval = shutdown (client_socket, SD_SEND);
618+ if (retval == SOCKET_ERROR) {
619+ fprintf (stderr, " shutdown failed: %d\n " , WSAGetLastError ());
625620 }
626621
627- // Display the client's address
628- retval = getnameinfo (
629- (SOCKADDR*)&from,
630- fromlen,
631- hoststr,
632- NI_MAXHOST,
633- servstr,
634- NI_MAXSERV,
635- NI_NUMERICHOST | NI_NUMERICSERV
636- );
637- if (retval != 0 )
638- {
639- fprintf (stderr, " getnameinfo failed: %d\n " , retval);
640- goto cleanup;
641- }
622+ closesocket (client_socket);
623+ client_socket = INVALID_SOCKET;
624+ }
642625
643- printf (" Accepted connection from host %s and port %s\n " ,
644- hoststr, servstr);
626+ } else {
627+ fromlen = sizeof (from);
628+ //
629+ // No client connection so wait for one
630+ //
631+ client_socket = accept (server_socket_handle, (SOCKADDR*)&from, &fromlen);
632+ if (client_socket == INVALID_SOCKET) {
633+ fprintf (stderr, " accept failed: %d\n " , WSAGetLastError ());
634+ closesocket (client_socket);
635+ client_socket = INVALID_SOCKET;
645636 }
646637 }
647638 }
648639
649- cleanup:
650-
651640 // Close the client connection if present
652641 if (client_socket != INVALID_SOCKET)
653642 {
@@ -712,4 +701,125 @@ bool CheckIfPortAvailable(short int dwPort) {
712701 }
713702}
714703
704+ #endif
705+ #pragma endregion
706+
707+ #pragma region TCP client
708+ #ifdef TCP_CLIENT
709+
710+ int CVCamStream::SetupClient () {
711+ framePointer = &frameBuffer[0 ];
712+
713+ WSAData wsaData;
714+ int iResult;
715+ SOCKET client_socket = INVALID_SOCKET;
716+ struct addrinfo * clientinfo = NULL ;
717+
718+ struct addrinfo hints;
719+
720+ // Initialize Winsock
721+ iResult = WSAStartup (MAKEWORD (2 , 2 ), &wsaData);
722+ if (iResult != 0 ) {
723+ fprintf (stderr, " WSAStartup failed with error: %d\n " , iResult);
724+ return 1 ;
725+ }
726+
727+ ZeroMemory (&hints, sizeof (hints));
728+ hints.ai_family = AF_INET;
729+ hints.ai_socktype = SOCK_STREAM;
730+ hints.ai_protocol = IPPROTO_TCP;
731+
732+ std::ostringstream oss;
733+ oss << DEFAULT_PORT;
734+
735+ // Resolve the server address and port
736+ iResult = getaddrinfo (" localhost" , oss.str ().c_str (), &hints, &clientinfo);
737+ if (iResult != 0 ) {
738+ fprintf (stderr, " getaddrinfo failed with error: %d\n " , iResult);
739+ WSACleanup ();
740+ return 1 ;
741+ }
742+
743+ client_info = TCPClientInfo (client_socket, clientinfo);
744+
745+ client_thread = CreateThread (
746+ NULL ,
747+ 0 ,
748+ ClientThread,
749+ (LPVOID)&client_info,
750+ 0 ,
751+ NULL
752+ );
753+ }
754+
755+ void CVCamStream::CleanupClient () {
756+ freeaddrinfo (client_info.addressinfo );
757+ closesocket (client_info.client_socket );
758+ CloseHandle (client_thread);
759+ WSACleanup ();
760+ }
761+
762+ DWORD WINAPI ClientThread (LPVOID lpParam) {
763+ TCPClientInfo* client_info_handle;
764+
765+ int retval,
766+ bytecount;
767+
768+ // Retrieve the socket handle
769+ client_info_handle = (TCPClientInfo*)lpParam;
770+ SOCKET client_socket_handle = client_info_handle->client_socket ;
771+
772+ for (;;) {
773+ if (client_socket_handle != INVALID_SOCKET) {
774+ // TODO: add method to request image and set format etc.
775+
776+ // Receive until the peer closes the connection
777+ bytecount = recv (client_socket_handle, (char *)frameBuffer, BUFFER_LENGTH, 0 );
778+ if (bytecount == SOCKET_ERROR) {
779+ // Lost connection
780+ fprintf (stderr, " recv failed with error: %d\n " , WSAGetLastError ());
781+ closesocket (client_socket_handle);
782+ client_socket_handle = INVALID_SOCKET;
783+ }
784+ else if (bytecount == 0 ) {
785+ // shutdown the connection since no more data will be sent
786+ retval = shutdown (client_socket_handle, SD_SEND);
787+ if (retval == SOCKET_ERROR) {
788+ fprintf (stderr, " shutdown failed with error: %d\n " , WSAGetLastError ());
789+ closesocket (client_socket_handle);
790+ client_socket_handle = INVALID_SOCKET;
791+ }
792+ client_socket_handle = INVALID_SOCKET;
793+ }
794+
795+ } else {
796+ // Create a SOCKET for connecting to server
797+ client_socket_handle = socket (client_info_handle->addressinfo ->ai_family , client_info_handle->addressinfo ->ai_socktype ,
798+ client_info_handle->addressinfo ->ai_protocol );
799+ if (client_socket_handle == INVALID_SOCKET) {
800+ fprintf (stderr, " socket failed with error: %ld\n " , WSAGetLastError ());
801+ closesocket (client_socket_handle);
802+ client_socket_handle = INVALID_SOCKET;
803+ }
804+
805+ // Connect to server.
806+ retval = connect (client_socket_handle, client_info_handle->addressinfo ->ai_addr , (int )client_info_handle->addressinfo ->ai_addrlen );
807+ if (retval == SOCKET_ERROR) {
808+ closesocket (client_socket_handle);
809+ client_socket_handle = INVALID_SOCKET;
810+ continue ;
811+ }
812+ }
813+ }
814+
815+ // Close the connection socket if needed
816+ if (client_socket_handle != INVALID_SOCKET) {
817+ closesocket (client_socket_handle);
818+ client_socket_handle = INVALID_SOCKET;
819+ }
820+
821+ return 0 ;
822+ }
823+
824+ #endif
715825#pragma endregion
0 commit comments