[haiku-commits] r39587 - haiku/trunk/src/add-ons/kernel/network/devices/dialup

  • From: philippe.houdoin@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 23 Nov 2010 18:30:50 +0100 (CET)

Author: phoudoin
Date: 2010-11-23 18:30:50 +0100 (Tue, 23 Nov 2010)
New Revision: 39587
Changeset: http://dev.haiku-os.org/changeset/39587

Modified:
   haiku/trunk/src/add-ons/kernel/network/devices/dialup/dialup.cpp
Log:
Initial send_data() support.


Modified: haiku/trunk/src/add-ons/kernel/network/devices/dialup/dialup.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/network/devices/dialup/dialup.cpp    
2010-11-23 17:15:25 UTC (rev 39586)
+++ haiku/trunk/src/add-ons/kernel/network/devices/dialup/dialup.cpp    
2010-11-23 17:30:50 UTC (rev 39587)
@@ -23,13 +23,18 @@
 #include <string.h>
 #include <unistd.h>
 #include <termios.h>
+#include <sys/uio.h>
 
+
+#define HDLC_FLAG_SEQUENCE     0x7e
 #define HDLC_CONTROL_ESCAPE    0x7d
-#define HDLC_FLAG_SEQUENCE     0x7e
+
 #define HDLC_ALL_STATIONS      0xff
 #define HDLC_UI                                0x03
 
+#define HDLC_HEADER_LENGTH     4
 
+
 enum dialup_state {
        DOWN,
        DIALING,
@@ -186,7 +191,7 @@
        if (status < B_OK)
                return status;
 
-       dialup_device* device = new (std::nothrow) dialup_device;
+       dialup_device* device = new (std::nothrow)dialup_device;
        if (device == NULL) {
                put_module(NET_BUFFER_MODULE_NAME);
                return B_NO_MEMORY;
@@ -197,9 +202,9 @@
        strcpy(device->name, name);
        device->flags = IFF_POINTOPOINT;
        device->type = IFT_PPP; // this device handle RFC 1331 frame format only
-       device->mtu = 1502;
+       device->mtu = 1500;
        device->media = 0;
-       device->header_length = 8; // HDLC_HEADER_LENGTH;
+       device->header_length = HDLC_HEADER_LENGTH;
        device->fd = -1;
        device->state = DOWN;
        device->data_mode = false;
@@ -224,6 +229,7 @@
        delete device;
 
        put_module(NET_BUFFER_MODULE_NAME);
+       gBufferModule = NULL;
        return B_OK;
 }
 
@@ -246,6 +252,8 @@
 
        // adjust options
        device->line_config.c_cflag &= ~CBAUD;
+       device->line_config.c_cflag &= CSIZE;
+       device->line_config.c_cflag &= CS8;
        device->line_config.c_cflag |= B115200; // TODO: make this configurable 
too...
        device->line_config.c_cflag |= (CLOCAL | CREAD);
        device->line_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
@@ -258,27 +266,31 @@
                sizeof(device->line_config)) < 0)
                goto err;
 
-       // TODO: init modem & start dialing phase
-       device->state = DIALING;
+       // init modem & start dialing phase
 
        char reply[32];
 
-       // Send modem init string
-       if (send_command(device, device->init_string) != B_OK
-               || read_command_reply(device, device->init_string,
-                       reply, sizeof(reply)) != B_OK
-               || strcmp(reply, "OK")) {
-               errno = B_IO_ERROR;
-               goto err;
+       if (strlen(device->init_string) > 0) {
+               // Send modem init string
+               if (send_command(device, device->init_string) != B_OK
+                       || read_command_reply(device, device->init_string,
+                               reply, sizeof(reply)) != B_OK
+                       || strcmp(reply, "OK")) {
+                       errno = B_IO_ERROR;
+                       goto err;
+               }
        }
 
-       // Send dialing string
-       if (send_command(device, device->dial_string) != B_OK
-               || read_command_reply(device, device->dial_string,
-                       reply, sizeof(reply)) != B_OK
-               || strncmp(reply, "CONNECT", 7)) {
-               errno = B_IO_ERROR;
-               goto err;
+       if (strlen(device->dial_string) > 0) {
+               // Send dialing string
+               device->state = DIALING;
+               if (send_command(device, device->dial_string) != B_OK
+                       || read_command_reply(device, device->dial_string,
+                               reply, sizeof(reply)) != B_OK
+                       || strncmp(reply, "CONNECT", 7)) {
+                       errno = B_IO_ERROR;
+                       goto err;
+               }
        }
 
        device->state = UP;
@@ -334,7 +346,88 @@
 status_t
 dialup_send_data(net_device* _device, net_buffer* buffer)
 {
-       return B_NOT_SUPPORTED;
+       dialup_device* device = (dialup_device*)_device;
+
+       if (device->fd == -1)
+               return B_FILE_ERROR;
+
+       dprintf("try to send HDLC packet of %lu bytes (flags %ld):\n", 
buffer->size, buffer->flags);
+
+       if (buffer->size < HDLC_HEADER_LENGTH)
+               return B_BAD_VALUE;
+
+       iovec* ioVectors = NULL;
+       iovec* ioVector;
+       uint8* packet = NULL;
+       int packetSize = 0;
+       status_t status;
+       ssize_t bytesWritten;
+
+       uint32 vectorCount = gBufferModule->count_iovecs(buffer);
+       if (vectorCount < 1) {
+               status = B_BAD_VALUE;
+               goto err;
+       }
+
+       ioVectors = (iovec*)malloc(sizeof(iovec)*vectorCount);
+       if (ioVectors == NULL) {
+               status = B_NO_MEMORY;
+               goto err;
+       }
+       gBufferModule->get_iovecs(buffer, ioVectors, vectorCount);
+
+       // encode HDLC packet
+
+       // worst case: begin and end sequence flags and each byte needing escape
+       packet = (uint8*) malloc(2 + 2 * buffer->size);
+       if (packet == NULL) {
+               status = B_NO_MEMORY;
+               goto err;
+       }
+
+       // mark frame start
+       packet[packetSize++] = HDLC_FLAG_SEQUENCE;
+
+       ioVector = ioVectors;
+       while (vectorCount--) {
+               uint8* data = (uint8*) ioVector->iov_base;
+               for (unsigned int i = 0; i < ioVector->iov_len; i++) {
+                       if (data[i] < 0x20
+                               || data[i] == HDLC_FLAG_SEQUENCE
+                               || data[i] == HDLC_CONTROL_ESCAPE) {
+                               // needs escape
+                               packet[packetSize++] = HDLC_CONTROL_ESCAPE;
+                               packet[packetSize++] = data[i] ^ 0x20;
+                       } else
+                               packet[packetSize++] = data[i];
+               }
+               // next io vector
+               ioVector++;
+       }
+       // mark frame end
+       packet[packetSize++] = HDLC_FLAG_SEQUENCE;
+
+       // send HDLC packet
+
+       bytesWritten = write(device->fd, packet, packetSize);
+       if (bytesWritten < 0) {
+               device->stats.send.errors++;
+               status = errno;
+               goto err;
+       }
+
+       device->stats.send.packets++;
+       device->stats.send.bytes += bytesWritten;
+       status = B_OK;
+       goto done;
+
+err:
+       device->stats.send.errors++;
+
+done:
+       free(ioVectors);
+       free(packet);
+       return status;
 }
 
 


Other related posts:

  • » [haiku-commits] r39587 - haiku/trunk/src/add-ons/kernel/network/devices/dialup - philippe . houdoin