ソースを参照

flow: add LineBuffer

ambrop7 15 年 前
コミット
188b71fe3f
3 ファイル変更173 行追加0 行削除
  1. 1 0
      flow/CMakeLists.txt
  2. 125 0
      flow/LineBuffer.c
  3. 47 0
      flow/LineBuffer.h

+ 1 - 0
flow/CMakeLists.txt

@@ -34,5 +34,6 @@ add_library(flow
     FlowError.c
     RouteBuffer.c
     PacketRouter.c
+    LineBuffer.c
 )
 target_link_libraries(flow system security)

+ 125 - 0
flow/LineBuffer.c

@@ -0,0 +1,125 @@
+/**
+ * @file LineBuffer.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <flow/LineBuffer.h>
+
+static void input_handler_done (LineBuffer *o, int data_len)
+{
+    DebugObject_Access(&o->d_obj);
+    ASSERT(data_len > 0)
+    ASSERT(data_len <= o->buf_size - o->buf_used)
+    
+    // update buffer
+    o->buf_used += data_len;
+    
+    // look for newline
+    int i;
+    for (i = o->buf_used - data_len; i < o->buf_used; i++) {
+        if (o->buf[i] == o->nl_char) {
+            break;
+        }
+    }
+    
+    if (i < o->buf_used || o->buf_used == o->buf_size) {
+        // pass to output
+        o->buf_consumed = (i < o->buf_used ? i + 1 : i);
+        PacketPassInterface_Sender_Send(o->output, o->buf, o->buf_consumed);
+    } else {
+        // receive more data
+        StreamRecvInterface_Receiver_Recv(o->input, o->buf + o->buf_used, o->buf_size - o->buf_used);
+    }
+}
+
+static void output_handler_done (LineBuffer *o)
+{
+    DebugObject_Access(&o->d_obj);
+    ASSERT(o->buf_consumed > 0)
+    ASSERT(o->buf_consumed <= o->buf_used)
+    
+    // update buffer
+    memmove(o->buf, o->buf + o->buf_consumed, o->buf_used - o->buf_consumed);
+    o->buf_used -= o->buf_consumed;
+    
+    // look for newline
+    int i;
+    for (i = 0; i < o->buf_used; i++) {
+        if (o->buf[i] == o->nl_char) {
+            break;
+        }
+    }
+    
+    if (i < o->buf_used || o->buf_used == o->buf_size) {
+        // pass to output
+        o->buf_consumed = (i < o->buf_used ? i + 1 : i);
+        PacketPassInterface_Sender_Send(o->output, o->buf, o->buf_consumed);
+    } else {
+        // receive more data
+        StreamRecvInterface_Receiver_Recv(o->input, o->buf + o->buf_used, o->buf_size - o->buf_used);
+    }
+}
+
+int LineBuffer_Init (LineBuffer *o, StreamRecvInterface *input, PacketPassInterface *output, int buf_size, uint8_t nl_char)
+{
+    ASSERT(buf_size > 0)
+    ASSERT(PacketPassInterface_GetMTU(output) >= buf_size)
+    
+    // init arguments
+    o->input = input;
+    o->output = output;
+    o->buf_size = buf_size;
+    o->nl_char = nl_char;
+    
+    // init input
+    StreamRecvInterface_Receiver_Init(o->input, (StreamRecvInterface_handler_done)input_handler_done, o);
+    
+    // init output
+    PacketPassInterface_Sender_Init(o->output, (PacketPassInterface_handler_done)output_handler_done, o);
+    
+    // set buffer empty
+    o->buf_used = 0;
+    
+    // allocate buffer
+    if (!(o->buf = malloc(o->buf_size))) {
+        DEBUG("malloc failed");
+        goto fail0;
+    }
+    
+    // start receiving
+    StreamRecvInterface_Receiver_Recv(o->input, o->buf, o->buf_size);
+    
+    DebugObject_Init(&o->d_obj);
+    return 1;
+    
+fail0:
+    return 0;
+}
+
+void LineBuffer_Free (LineBuffer *o)
+{
+    DebugObject_Free(&o->d_obj);
+    
+    // free buffer
+    free(o->buf);
+}

+ 47 - 0
flow/LineBuffer.h

@@ -0,0 +1,47 @@
+/**
+ * @file LineBuffer.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BADVPN_FLOW_LINEBUFFER_H
+#define BADVPN_FLOW_LINEBUFFER_H
+
+#include <stdint.h>
+
+#include <misc/debug.h>
+#include <system/DebugObject.h>
+#include <flow/StreamRecvInterface.h>
+#include <flow/PacketPassInterface.h>
+
+typedef struct {
+    StreamRecvInterface *input;
+    PacketPassInterface *output;
+    int buf_size;
+    uint8_t nl_char;
+    int buf_used;
+    uint8_t *buf;
+    int buf_consumed;
+    DebugObject d_obj;
+} LineBuffer;
+
+int LineBuffer_Init (LineBuffer *o, StreamRecvInterface *input, PacketPassInterface *output, int buf_size, uint8_t nl_char) WARN_UNUSED;
+void LineBuffer_Free (LineBuffer *o);
+
+#endif