Commit fc6ef99a authored by jan.koester's avatar jan.koester
Browse files

test

parent f53f26d9
Loading
Loading
Loading
Loading
+54 −62
Original line number Diff line number Diff line
@@ -154,29 +154,6 @@ namespace netplus {

    class EventWorker {
    public:
		// Inside the IOCP Worker logic
		void EventWorker::start_read(client* ctx) {
			con& c = *ctx->CurCon;
			buffer buf(ctx->readCtx.buffer, BLOCKSIZE);

			if (c.csock->_Type == sockettype::UDP) {
				// Cast to UDP to access the WSA-specific methods
				static_cast<udp*>(c.csock.get())->recvDataWSA(buf, 0);
			}
		}

		void EventWorker::start_write(client* ctx) {
			con& c = *ctx->CurCon;
			if (c.SendData.empty()) return;

			size_t toSend = std::min<size_t>(BLOCKSIZE, c.SendData.size());
			buffer out(c.SendData.data(), toSend);

			if (c.csock->_Type == sockettype::UDP) {
				static_cast<udp*>(c.csock.get())->sendDataWSA(out, 0);
			}
		}

        EventWorker(int tid, ULONG_PTR args, EventWorkerArgs* eargs) {
            while (event::Running) {
                DWORD dwBytesTransfered = 0;
@@ -201,44 +178,59 @@ namespace netplus {

                try {
                    std::lock_guard<std::mutex> guard(pClientContext->cltmtx);

					if (pIoCtx->operation == OP_READ) {
                        // SSL vs Plaintext Decryption Logic
						if (c.csock->_Type == sockettype::SSL) {
                            // Feed encrypted data to SSL engine; recvData should return plaintext
                            buffer enc(pIoCtx->buffer, dwBytesTransfered);
                            c.csock->recvData(enc, 0);
                        } else {
                            c.RecvData.append(pIoCtx->buffer, dwBytesTransfered);
                        }
							// CAST required because recvData in SSL class handles the decryption state
							ssl* sslSocket = static_cast<ssl*>(c.csock.get());

                        // Notify Protocol Layer
                        eargs->event->RequestEvent(c, tid, args);
							// 1. Prepare a buffer for the plaintext
							buffer plain(BLOCKSIZE);

                        // Decide next step: Write if data queued, else keep reading
                        if (!c.SendData.empty()) {
                            start_write(pClientContext);
                        } else {
                            start_read(pClientContext);
							// 2. This call takes the ciphertext (automatically filled by IOCP into _rx_netbuf)
							// and decrypts it into our 'plain' buffer.
							size_t decrypted = sslSocket->recvData(plain, 0);

							if (decrypted > 0) {
								c.RecvData.append(plain.data.buf, decrypted);
								eargs->event->RequestEvent(c, tid, args);
							}

                    } else if (pIoCtx->operation == OP_WRITE) {
                        // For SSL, we track plaintext consumed, but IOCP tells us bytes sent on wire.
                        // We erase based on the application layer's queue management.
                        if (c.csock->_Type == sockettype::SSL) {
                             // SSL layers handle SendData erasure internally or via return codes
							// 3. Request more ciphertext from the wire
							sslSocket->recvDataWSA(c.RecvData, 0);
						} else {
                            c.SendData.erase(c.SendData.begin(), c.SendData.begin() + dwBytesTransfered);
							// Standard TCP: Direct append and re-read
							c.RecvData.append(pIoCtx->buffer, dwBytesTransfered);
							eargs->event->RequestEvent(c, tid, args);
							static_cast<tcp*>(c.csock.get())->recvDataWSA(c.RecvData, 0);
						}
                    } else if (pIoCtx->operation == OP_WRITE) {
						// 1. Remove the bytes that were successfully sent from the SendData buffer
						// For TCP/UDP, dwBytesTransfered represents the raw bytes on the wire.
						// For SSL, sendDataWSA handles the internal plaintext tracking.
						c.SendData.erase(0, dwBytesTransfered);

						// 2. Trigger ResponseEvent if the buffer is now empty to let the user add more data
						if (c.SendData.empty()) {
                            eargs->event->ResponseEvent(c, tid, args);
							eargs->event->ResponseEvent(c, tid, (ULONG_PTR)eargs->args);
						}

						// 3. Continue the write loop if there is remaining data
						if (!c.SendData.empty()) {
                            start_write(pClientContext);
							// Prepare a buffer object for the next chunk
							size_t toSend = std::min<size_t>(BLOCKSIZE, c.SendData.size());
							buffer out(c.SendData.data(), toSend);

							// 4. Use the specialized WSA methods based on socket type
							if (c.csock->_Type == sockettype::TCP) {
								static_cast<tcp*>(c.csock.get())->sendDataWSA(out, 0);
							} else if (c.csock->_Type == sockettype::UDP) {
								static_cast<udp*>(c.csock.get())->sendDataWSA(out, 0);
							} else if (c.csock->_Type == sockettype::SSL) {
								// This method encrypts the plaintext in c.SendData and initiates a WSASend
								static_cast<ssl*>(c.csock.get())->sendDataWSA(out, 0);
							}
						} else {
                            start_read(pClientContext);
							// If nothing left to write, switch back to listening for data
							EventWorker::start_read(pClientContext);
						}
					}
                } catch (NetException& e) {
+4 −1
Original line number Diff line number Diff line
@@ -221,7 +221,10 @@ namespace netplus {

        size_t sendData(buffer &data, int flags = 0) override;
        size_t recvData(buffer &data, int flags = 0) override;

#ifdef Windows
        size_t sendDataWSA(buffer &data, int flags = 0);
        size_t recvDataWSA(buffer &data, int flags = 0);
#endif
        bool loadServerPrivateKeyDer(const std::string& keyDerPath);

        bool hasPendingWrite() const override {
+63 −0
Original line number Diff line number Diff line
@@ -1774,3 +1774,66 @@ std::vector<uint8_t> netplus::ssl::_decryptRecordCBC(uint8_t recType,
}

bool loadServerPrivateKeyDer(const std::string& keyDerPath);

#ifdef Windows
size_t netplus::ssl::sendDataWSA(buffer &data, int flags) {
    if (!_handshakeDone) {
        // Handshake logic usually handled via standard sendData
        // until the secure channel is established.
        return 0;
    }

    // 1. Encrypt the plaintext data into a TLS Record
    // This utilizes your existing internal encryption logic
    std::vector<uint8_t> plaintext(
        data.ptr ? data.data.ptr : data.data.buf,
        (data.ptr ? data.data.ptr : data.data.buf) + data.size
    );

    // This internal helper should append the encrypted record to _send_record
    _sendEncryptedRecord(this, 23, plaintext); // 23 = Application Data

    // 2. Prepare the encrypted buffer for the WSA call
    buffer wsa_out((char*)_send_record.data() + _send_off, _send_record.size() - _send_off);

    // 3. Call the parent tcp implementation to initiate the IOCP write
    return tcp::sendDataWSA(wsa_out, flags);
}

size_t netplus::ssl::recvData(buffer &data, int flags) {
    // 1. Process ciphertext that was placed in _rx_netbuf by the IOCP
    if (!_rx_netbuf.empty()) {
        // Append new network data to our decryption record buffer
        _recv_record.insert(_recv_record.end(), _rx_netbuf.begin(), _rx_netbuf.end());
        _rx_netbuf.clear(); // Clear for next WSA request
    }

    // 2. Attempt to decrypt a full TLS record
    if (_recv_record.size() >= 5) { // Minimum TLS Header size
        uint8_t type = _recv_record[0];
        uint16_t version = (_recv_record[1] << 8) | _recv_record[2];
        uint16_t length = (_recv_record[3] << 8) | _recv_record[4];

        if (_recv_record.size() >= (size_t)(5 + length)) {
            std::vector<uint8_t> fragment(
                _recv_record.begin() + 5,
                _recv_record.begin() + 5 + length
            );

            // 3. Decrypt the fragment using your CBC helper
            std::vector<uint8_t> plaintext = _decryptRecordCBC(type, version, fragment);

            // 4. Copy decrypted plaintext to the user-provided buffer
            size_t toCopy = std::min(data.size, plaintext.size());
            memcpy(data.data.buf, plaintext.data(), toCopy);

            // Remove the processed record from the internal buffer
            _recv_record.erase(_recv_record.begin(), _recv_record.begin() + 5 + length);

            return toCopy;
        }
    }
    return 0; // No full record decrypted yet
}

#endif