#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
#include "apr_getopt.h"
#define STRLEN 15
static void closeapr(void)
{
apr_terminate();
}
int main(int argc, const char * const argv[])
{
apr_pool_t *context;
apr_socket_t *sock;
apr_socket_t *sock2;
apr_size_t length;
apr_int32_t rv;
apr_pollfd_t *sdset;
char datasend[STRLEN];
char datarecv[STRLEN] = "Recv data test";
const char *bind_to_ipaddr = NULL;
char *local_ipaddr, *remote_ipaddr;
apr_port_t local_port, remote_port;
apr_sockaddr_t *localsa = NULL, *remotesa;
apr_status_t stat;
int family = APR_UNSPEC;
char buf[128];
apr_getopt_t *opt;
const char *optarg;
char optchar;
fprintf(stdout, "Initializing.........");
if (apr_initialize() != APR_SUCCESS) {
fprintf(stderr, "Something went wrong\n");
exit(-1);
}
fprintf(stdout, "OK\n");
atexit(closeapr);
fprintf(stdout, "Creating context.......");
if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
fprintf(stderr, "Could not create a context\n");
exit(-1);
}
fprintf(stdout, "OK\n");
if (apr_getopt_init(&opt, context, argc, argv)) {
fprintf(stderr, "failed to initialize opts\n");
exit(-1);
}
while ((stat = apr_getopt(opt, "i:", &optchar, &optarg)) == APR_SUCCESS) {
switch(optchar) {
case 'i':
bind_to_ipaddr = optarg;
break;
}
}
if (stat != APR_EOF) {
fprintf(stderr,
"usage: %s [-i local-interface-address]\n",
argv[0]);
exit(-1);
}
if (bind_to_ipaddr) {
/* First, parse/resolve ipaddr so we know what address family of
* socket we need. We'll use the returned sockaddr later when
* we bind.
*/
stat = apr_sockaddr_info_get(&localsa, bind_to_ipaddr, APR_UNSPEC, 8021, 0,
context);
if (stat != APR_SUCCESS) {
fprintf(stderr,
"Couldn't build the socket address correctly: %s\n",
apr_strerror(stat, buf, sizeof buf));
exit(-1);
}
family = localsa->sa.sin.sin_family;
}
fprintf(stdout, "\tServer: Creating new socket.......");
if (apr_socket_create(&sock, family, SOCK_STREAM, context) != APR_SUCCESS) {
fprintf(stderr, "Couldn't create socket\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Setting socket option NONBLOCK.......");
if (apr_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Couldn't set socket option\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Setting socket option REUSEADDR.......");
if (apr_setsocketopt(sock, APR_SO_REUSEADDR, 1) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Couldn't set socket option\n");
exit(-1);
}
fprintf(stdout, "OK\n");
if (!localsa) {
apr_socket_addr_get(&localsa, APR_LOCAL, sock);
apr_sockaddr_port_set(localsa, 8021);
}
fprintf(stdout, "\tServer: Binding socket to port.......");
if ((stat = apr_bind(sock, localsa)) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Could not bind: %s\n",
apr_strerror(stat, buf, sizeof buf));
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Listening to socket.......");
if (apr_listen(sock, 5) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Could not listen\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Setting up socket for polling.......");
apr_poll_setup(&sdset, 1, context);
apr_poll_socket_add(sdset, sock, APR_POLLIN);
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Beginning to poll for socket.......");
rv = 1;
if (apr_poll(sdset, &rv, -1) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Select caused an error\n");
exit(-1);
}
else if (rv == 0) {
apr_socket_close(sock);
fprintf(stderr, "I should not return until rv == 1\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Accepting a connection.......");
if (apr_accept(&sock2, sock, context) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Could not accept connection.\n");
exit(-1);
}
fprintf(stdout, "OK\n");
apr_socket_addr_get(&remotesa, APR_REMOTE, sock2);
apr_sockaddr_ip_get(&remote_ipaddr, remotesa);
apr_sockaddr_port_get(&remote_port, remotesa);
apr_socket_addr_get(&localsa, APR_LOCAL, sock2);
apr_sockaddr_ip_get(&local_ipaddr, localsa);
apr_sockaddr_port_get(&local_port, localsa);
fprintf(stdout, "\tServer socket: %s:%u -> %s:%u\n", local_ipaddr, local_port, remote_ipaddr, remote_port);
length = STRLEN;
fprintf(stdout, "\tServer: Trying to recv data from socket.......");
if (apr_recv(sock2, datasend, &length) != APR_SUCCESS) {
apr_socket_close(sock);
apr_socket_close(sock2);
fprintf(stderr, "Problem recving data\n");
exit(-1);
}
if (strcmp(datasend, "Send data test")) {
apr_socket_close(sock);
apr_socket_close(sock2);
fprintf(stderr, "I did not receive the correct data %s\n", datarecv);
exit(-1);
}
fprintf(stdout, "OK\n");
length = STRLEN;
fprintf(stdout, "\tServer: Sending data over socket.......");
if (apr_send(sock2, datarecv, &length) != APR_SUCCESS) {
apr_socket_close(sock);
apr_socket_close(sock2);
fprintf(stderr, "Problem sending data\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: Shutting down accepted socket.......");
if (apr_shutdown(sock2, APR_SHUTDOWN_READ) != APR_SUCCESS) {
apr_socket_close(sock);
apr_socket_close(sock2);
fprintf(stderr, "Problem shutting down\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: closing duplicate socket.......");
if (apr_socket_close(sock2) != APR_SUCCESS) {
apr_socket_close(sock);
fprintf(stderr, "Problem closing down\n");
exit(-1);
}
fprintf(stdout, "OK\n");
fprintf(stdout, "\tServer: closing original socket.......");
if (apr_socket_close(sock) != APR_SUCCESS) {
fprintf(stderr, "Problem closing down\n");
exit(-1);
}
fprintf(stdout, "OK\n");
return 1;
}
1.1 apr-site/apr2_0intro/Server/Server.dsp
Index: Server.dsp
===================================================================
# Microsoft Developer Studio Project File - Name="Server" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Server - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Server.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Server.mak" CFG="Server - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Server - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Server - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Server - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD BASE RSC /l 0x1009 /d "NDEBUG"
# ADD RSC /l 0x1009 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "Server - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x1009 /d "_DEBUG"
# ADD RSC /l 0x1009 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "Server - Win32 Release"
# Name "Server - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Server.cpp
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"stdafx.h"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Group "Library Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\bin\libapr.lib
# End Source File
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project
1.1 apr-site/apr2_0intro/Server/Server.plg
Index: Server.plg
===================================================================
Build Log
--------------------Configuration: Server - Win32 Debug--------------------
Command Lines
Creating temporary file "C:\DOCUME~1\cgross\LOCALS~1\Temp\RSP69.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/Server.pdb" /debug /machine:I386 /out:"Debug/Server.exe" /pdbtype:sept
.\Debug\StdAfx.obj
.\Debug\Server.obj
..\..\..\bin\libapr.lib
]
Creating command line "link.exe @C:\DOCUME~1\cgross\LOCALS~1\Temp\RSP69.tmp"
Output Window
Linking...
Results
Server.exe - 0 error(s), 0 warning(s)
1.1 apr-site/apr2_0intro/Server/StdAfx.cpp
Index: StdAfx.cpp
===================================================================
// stdafx.cpp : source file that includes just the standard includes
// Server.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
1.1 apr-site/apr2_0intro/Server/StdAfx.h
Index: StdAfx.h
===================================================================
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__20F637F4_0BAF_4E05_B36E_D8E524EB176B__INCLUDED_)
#define AFX_STDAFX_H__20F637F4_0BAF_4E05_B36E_D8E524EB176B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include
// TODO: reference additional headers your program requires here
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__20F637F4_0BAF_4E05_B36E_D8E524EB176B__INCLUDED_)