void SocketStreamHandle::platformClose() { LOG(Network, "SocketStreamHandle %p platformClose", this); // We remove this handle from the active handles list first, to disable all callbacks. deactivateHandle(this); stopWaitingForSocketWritability(); if (m_socketConnection) { GOwnPtr<GError> error; g_io_stream_close(G_IO_STREAM(m_socketConnection.get()), 0, &error.outPtr()); if (error) m_client->didFailSocketStream(this, SocketStreamError(error->code, error->message)); m_socketConnection = 0; } m_outputStream = 0; m_inputStream = 0; delete m_readBuffer; m_readBuffer = 0; m_client->didCloseSocketStream(this); }
void SocketStreamHandle::connected(GSocketConnection* socketConnection, GError* error) { if (error) { m_client->didFailSocketStream(this, SocketStreamError(error->code)); return; } m_socketConnection = adoptGRef(socketConnection); m_outputStream = G_POLLABLE_OUTPUT_STREAM(g_io_stream_get_output_stream(G_IO_STREAM(m_socketConnection.get()))); m_inputStream = g_io_stream_get_input_stream(G_IO_STREAM(m_socketConnection.get())); m_readBuffer = new char[READ_BUFFER_SIZE]; g_input_stream_read_async(m_inputStream.get(), m_readBuffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT, 0, reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), m_id); // The client can close the handle, potentially removing the last reference. RefPtr<SocketStreamHandle> protect(this); m_state = Open; m_client->didOpenSocketStream(this); if (!m_socketConnection) // Client closed the connection. return; }
int SocketStreamHandle::platformSend(const char* data, int length) { LOG(Network, "SocketStreamHandle %p platformSend", this); if (!m_outputStream || !data) return 0; GOwnPtr<GError> error; gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, 0, &error.outPtr()); if (error) { if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) beginWaitingForSocketWritability(); else m_client->didFailSocketStream(this, SocketStreamError(error->code, error->message)); return 0; } // If we did not send all the bytes we were given, we know that // SocketStreamHandleBase will need to send more in the future. if (written < length) beginWaitingForSocketWritability(); return written; }
void SocketStreamHandle::readStreamCallback(CFStreamEventType type) { switch(type) { case kCFStreamEventNone: break; case kCFStreamEventOpenCompleted: break; case kCFStreamEventHasBytesAvailable: { if (m_connectingSubstate == WaitingForConnect) { if (m_connectionType == CONNECTProxy) { RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get())); if (proxyResponse && (407 == CFHTTPMessageGetResponseStatusCode(proxyResponse.get()))) { addCONNECTCredentials(proxyResponse.get()); return; } } } else if (m_connectingSubstate == WaitingForCredentials) break; if (m_connectingSubstate == WaitingForConnect) { m_connectingSubstate = Connected; m_state = Open; RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference. m_client->didOpen(this); if (m_state == Closed) break; // Fall through. } else if (m_state == Closed) break; ASSERT(m_state == Open); ASSERT(m_connectingSubstate == Connected); CFIndex length; UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything. const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length); if (!ptr) { length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer)); ptr = localBuffer; } m_client->didReceiveData(this, reinterpret_cast<const char*>(ptr), length); break; } case kCFStreamEventCanAcceptBytes: ASSERT_NOT_REACHED(); break; case kCFStreamEventErrorOccurred: { #ifndef BUILDING_ON_TIGER RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get())); reportErrorToClient(error.get()); #else CFStreamError error = CFReadStreamGetError(m_readStream.get()); m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error. #endif break; } case kCFStreamEventEndEncountered: platformClose(); break; } }
void SocketStreamHandle::readStreamCallback(CFStreamEventType type) { switch(type) { case kCFStreamEventNone: break; case kCFStreamEventOpenCompleted: break; case kCFStreamEventHasBytesAvailable: { if (m_connectingSubstate == WaitingForConnect) { if (m_connectionType == CONNECTProxy) { RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get())); if (proxyResponse) { CFIndex proxyResponseCode = CFHTTPMessageGetResponseStatusCode(proxyResponse.get()); switch (proxyResponseCode) { case 200: // Successful connection. break; case 407: addCONNECTCredentials(proxyResponse.get()); return; default: m_client->didFailSocketStream(this, SocketStreamError(static_cast<int>(proxyResponseCode), m_url.string(), "Proxy connection could not be established")); platformClose(); return; } } } } else if (m_connectingSubstate == WaitingForCredentials) break; if (m_connectingSubstate == WaitingForConnect) { m_connectingSubstate = Connected; m_state = Open; m_client->didOpenSocketStream(this); if (m_state == Closed) break; // Fall through. } else if (m_state == Closed) break; ASSERT(m_state == Open); ASSERT(m_connectingSubstate == Connected); CFIndex length; UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything. const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length); if (!ptr) { length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer)); ptr = localBuffer; } m_client->didReceiveSocketStreamData(this, reinterpret_cast<const char*>(ptr), length); break; } case kCFStreamEventCanAcceptBytes: ASSERT_NOT_REACHED(); break; case kCFStreamEventErrorOccurred: { RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get())); reportErrorToClient(error.get()); break; } case kCFStreamEventEndEncountered: platformClose(); break; } }
void SocketStreamHandleServer::progressTimerFired() { switch (m_progressState) { case EError: if (m_client) m_client->didFailSocketStream(reinterpret_cast<SocketStreamHandle*>(this), SocketStreamError(-1)); break; case EConnectingDest: break; #if 0 case EConnectingProxy: { char buf[1024] = {0}; fd_set rd; FD_ZERO(&rd); FD_SET(m_socket, &rd); struct timeval tv = {0}; if (wkcNetSelectPeer(m_socket+1, &rd, NULL, NULL, &tv)==0) { m_progressTimer.startOneShot(0.1); break; } int len = wkcNetRecvPeer(m_socket, buf, sizeof(buf), 0); if (len<=0) { m_progressTimer.startOneShot(0.1); break; } String result(buf); if (result.find("Connection Established", 0, false)) { m_progressState = EConnected; m_progressTimer.startOneShot(0.1); } else { m_progressState = EError; m_progressTimer.startOneShot(0.1); } break; } #endif case EConnected: m_state = Open; m_progressState = EReady; if (m_client) m_client->didOpenSocketStream(reinterpret_cast<SocketStreamHandle*>(this)); m_progressTimer.startOneShot(0.1); break; case EReady: { char buf[1024] = {0}; do { fd_set rd, wd; FD_ZERO(&rd); FD_ZERO(&wd); FD_SET(m_socket, &rd); FD_SET(m_socket, &wd); struct timeval tv = {0}; int ret = wkcNetSelectPeer(m_socket+1, &rd, &wd, NULL, &tv); if (ret == 0 || (!FD_ISSET(m_socket, &rd) && !bufferedAmount())) break; if (FD_ISSET(m_socket, &rd)) { int len = wkcNetRecvPeer(m_socket, buf, sizeof(buf), 0); if (len<=0) break; if (m_client) m_client->didReceiveSocketStreamData(reinterpret_cast<SocketStreamHandle*>(this), buf, len); } if (bufferedAmount()) { if (FD_ISSET(m_socket, &wd)) { if (!sendPendingData()) { m_progressState = EError; break; } } } } while (1); m_progressTimer.startOneShot(0.1); break; } case ERequestClose: if (m_client) m_client->didCloseSocketStream(reinterpret_cast<SocketStreamHandle*>(this)); m_state = Closed; break; default: break; } }
void SocketStreamHandle::didFail(int errorCode, const String& errorDescription) { m_client->didFailSocketStream( this, SocketStreamError(errorCode, m_url.string(), errorDescription)); }