[prev in list] [next in list] [prev in thread] [next in thread]
List: apr-cvs
Subject: svn commit: r649390 - /apr/apr/trunk/file_io/win32/pipe.c
From: mturk () apache ! org
Date: 2008-04-18 7:18:25
Message-ID: 20080418071825.723B91A9832 () eris ! apache ! org
[Download RAW message or body]
Author: mturk
Date: Fri Apr 18 00:18:23 2008
New Revision: 649390
URL: http://svn.apache.org/viewvc?rev=649390&view=rev
Log:
Implement apr_file_socket_pipe_create for windows. Private for implementing \
pollset_wakeup caused by !APR_FILES_AS_SOCKETS
Modified:
apr/apr/trunk/file_io/win32/pipe.c
Modified: apr/apr/trunk/file_io/win32/pipe.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/file_io/win32/pipe.c?rev=649390&r1=649389&r2=649390&view=diff
==============================================================================
--- apr/apr/trunk/file_io/win32/pipe.c (original)
+++ apr/apr/trunk/file_io/win32/pipe.c Fri Apr 18 00:18:23 2008
@@ -225,3 +225,186 @@
{
return apr_os_pipe_put_ex(file, thefile, 0, pool);
}
+
+static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr)
+{
+ static int id = 0;
+
+ SOCKET ls;
+ struct sockaddr_in pa;
+ struct sockaddr_in la;
+ struct sockaddr_in ca;
+ int nrd;
+ apr_status_t rv = APR_SUCCESS;
+ int ll = sizeof(la);
+ int lc = sizeof(ca);
+ int bm = 1;
+ int uid[2];
+ int iid[2];
+
+ *rd = INVALID_SOCKET;
+ *wr = INVALID_SOCKET;
+
+ /* Create the unique socket identifier
+ * so that we know the connection originated
+ * from us.
+ */
+ uid[0] = getpid();
+ uid[1] = id++;
+ if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+ return apr_get_netos_error();
+ }
+
+ pa.sin_family = AF_INET;
+ pa.sin_port = 0;
+ pa.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ if (listen(ls, 1) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ if (send(*wr, (char *)uid, sizeof(uid), 0) != sizeof(uid)) {
+ if ((rv = apr_get_netos_error()) == 0) {
+ rv = APR_EINVAL;
+ }
+ goto cleanup;
+ }
+ if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ for (;;) {
+ /* Listening socket is nonblocking by now.
+ * The accept must create the socket
+ * immediatelly because we connected already.
+ */
+ if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ /* Verify the connection by reading the send identification.
+ */
+ nrd = recv(*rd, (char *)iid, sizeof(iid), 0);
+ if (nrd == sizeof(iid)) {
+ if (memcmp(uid, iid, sizeof(uid)) == 0) {
+ /* Wow, we recived what we send.
+ * Put read side of the pipe to the blocking
+ * mode and return.
+ */
+ bm = 0;
+ if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ break;
+ }
+ }
+ else if (nrd == SOCKET_ERROR) {
+ rv = apr_get_netos_error();
+ goto cleanup;
+ }
+ closesocket(*rd);
+ }
+ /* We don't need the listening socket any more */
+ closesocket(ls);
+ return 0;
+
+cleanup:
+ /* Don't leak resources */
+ if (*rd != INVALID_SOCKET)
+ closesocket(*rd);
+ if (*wr != INVALID_SOCKET)
+ closesocket(*wr);
+
+ *rd = INVALID_SOCKET;
+ *wr = INVALID_SOCKET;
+ closesocket(ls);
+ return rv;
+}
+
+static apr_status_t socket_pipe_cleanup(void *thefile)
+{
+ apr_file_t *file = thefile;
+ if (file->filehand != INVALID_HANDLE_VALUE) {
+ shutdown((SOCKET)file->filehand, SD_BOTH);
+ closesocket((SOCKET)file->filehand);
+ file->filehand = INVALID_HANDLE_VALUE;
+ }
+ return APR_SUCCESS;
+}
+
+#if 0
+/* XXX Do we need this as public API or APR private ?
+ * It's main usage is for interrupting pollset because
+ * of !APR_FILES_AS_SOCKETS.
+ * Duplicating sockets in child requires WSADuplicateSocket
+ * and passing WSAPROTOCOL_INFO data to the child, so we
+ * would need some sort of IPC instead DuplicateHandle used
+ * for files and pipes.
+ */
+APR_DECLARE(apr_status_t)
+#else
+apr_status_t
+#endif
+apr_file_socket_pipe_create(apr_file_t **in,
+ apr_file_t **out,
+ apr_pool_t *p)
+{
+ apr_status_t rv;
+ SOCKET rd;
+ SOCKET wr;
+
+ if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) {
+ return rv;
+ }
+ (*in) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
+ (*in)->pool = p;
+ (*in)->fname = NULL;
+ (*in)->pipe = 1;
+ (*in)->timeout = -1;
+ (*in)->ungetchar = -1;
+ (*in)->eof_hit = 0;
+ (*in)->filePtr = 0;
+ (*in)->bufpos = 0;
+ (*in)->dataRead = 0;
+ (*in)->direction = 0;
+ (*in)->pOverlapped = (OVERLAPPED*)apr_pcalloc(p, sizeof(OVERLAPPED));
+ (*in)->filehand = (HANDLE)rd;
+
+ (*out) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
+ (*out)->pool = p;
+ (*out)->fname = NULL;
+ (*out)->pipe = 1;
+ (*out)->timeout = -1;
+ (*out)->ungetchar = -1;
+ (*out)->eof_hit = 0;
+ (*out)->filePtr = 0;
+ (*out)->bufpos = 0;
+ (*out)->dataRead = 0;
+ (*out)->direction = 0;
+ (*out)->pOverlapped = (OVERLAPPED*)apr_pcalloc(p, sizeof(OVERLAPPED));
+ (*out)->filehand = (HANDLE)wr;
+
+ apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup,
+ apr_pool_cleanup_null);
+ apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup,
+ apr_pool_cleanup_null);
+
+ return rv;
+}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic