Stream Parsing & Buffer Management¶
SIP traffic over TCP or TLS arrives in continuous stream buffers where multiple SIP frames can be packed together, or where a single frame might be partially received. sip2json::parseAsync processes frames directly off network read buffers with move semantics.
1. Stream Buffer Data Flow Workflow¶
sequenceDiagram
autonumber
participant Net as Network Socket (TCP/TLS)
participant Buf as Buffer (std::string_view or std::string)
participant Parser as sip2json::parseAsync
participant App as Application Handler
Net->>Buf: Read raw bytes into buffer
Buf->>Parser: Pass buffer view or string reference
loop For each complete SIP message
Parser->>Parser: Extract Startline & Headers (zero-copy string_view)
Parser->>Parser: Parse SDP Body (if present)
Parser->>App: Invoke Callback with sipmessage&& (Move)
Parser->>Buf: Advance view or erase consumed bytes
end
alt Incomplete Message / Partial Frame
Parser-->>Buf: Stop parsing, leave residual bytes in place
end
2. Stream Processing Mechanics¶
sip2json::parseAsync provides two streaming modes:
Zero-Copy Stream (std::string_view&)¶
Advances the non-owning view in-place past all successfully parsed messages and returns the total bytes consumed:
#include <iostream>
#include <string_view>
#include "siddiqsoft/sip2json.hpp"
using namespace siddiqsoft;
void onNetworkBufferReceived(std::string_view& tcpReadBuffer)
{
// Decodes frames and advances tcpReadBuffer past consumed bytes
size_t consumed = sip2json::parseAsync(
tcpReadBuffer,
[](sipmessage&& msg) {
std::cout << "Method: " << msg.getMethodView()
<< ", Call-ID: " << msg.getCallIDView() << "\n";
},
[](const sip2json_exception& ex, std::string_view remaining) {
std::cerr << "Parser diagnostic: " << ex.what() << "\n";
}
);
}
In-Place Buffer Drainage (std::string&)¶
For persistent std::string socket read buffers, parseAsync automatically erases consumed bytes from the front of the string, retaining incomplete frames for subsequent network recv() cycles:
#include <iostream>
#include <string>
#include "siddiqsoft/sip2json.hpp"
using namespace siddiqsoft;
void onNetworkBufferReceived(std::string& tcpBuffer)
{
// Automatically drains consumed frames; residual bytes remain in tcpBuffer
sip2json::parseAsync(
tcpBuffer,
[](sipmessage&& msg) {
std::cout << "Method: " << msg.getMethod()
<< ", Call-ID: " << msg.getCallID() << "\n";
},
[](const sip2json_exception& ex, std::string::iterator& start, const std::string::iterator& end) {
std::cerr << "Parser diagnostic: " << ex.what() << "\n";
}
);
}
3. Memory Layout & Lifetime Rules¶
- Move Semantics (
std::move): Messages passed to parsing callbacks are rvalue references (sipmessage&&). The parser constructs the object in-place and transfers ownership directly to the application callback. If you need to preserve message state beyond callback scope, explicitly copy or move the object. - Buffer Residuals & In-Place Drainage: If a partial frame remains at the end of the buffer,
parseAsyncstops and leavescursorpointing to the beginning of the incomplete frame. DrainingtcpBuffer.erase(tcpBuffer.begin(), cursor)retains residual bytes for subsequent networkrecv()cycles without reallocation. - Zero Allocation Tokenization: Header and startline identification uses
std::string_viewslices and 64-bit FNV-1a hash matching (switch (h)), completely eliminating intermediate string allocations orstd::transformloops. - Predictable Container Layout: Headers and multi-value header arrays are stored using standard library vectors and maps for predictable memory alignment and cache locality.