Changeset 7b64cf0 in mainline
- Timestamp:
- 2013-05-16T11:09:44Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4510e06
- Parents:
- 2093fbe
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/slip/slip.c
r2093fbe r7b64cf0 36 36 37 37 #include <stdio.h> 38 #include <stdint.h> 38 39 #include <loc.h> 39 40 #include <inet/iplink_srv.h> 41 #include <device/char_dev.h> 40 42 #include <io/log.h> 41 43 #include <errno.h> … … 45 47 46 48 #define SLIP_MTU 1006 /* as per RFC 1055 */ 49 50 #define SLIP_END 0300 51 #define SLIP_ESC 0333 52 #define SLIP_ESC_END 0334 53 #define SLIP_ESC_ESC 0335 47 54 48 55 static int slip_open(iplink_srv_t *); … … 64 71 }; 65 72 73 static uint8_t slip_send_buf[SLIP_MTU + 2]; 74 static size_t slip_send_pending; 75 76 static uint8_t slip_recv_buf[SLIP_MTU + 2]; 77 static size_t slip_recv_pending; 78 static size_t slip_recv_read; 79 66 80 int slip_open(iplink_srv_t *srv) 67 81 { … … 76 90 } 77 91 92 static void write_flush(async_sess_t *sess) 93 { 94 size_t written = 0; 95 96 while (slip_send_pending > 0) { 97 ssize_t size; 98 99 size = char_dev_write(sess, &slip_send_buf[written], 100 slip_send_pending); 101 if (size < 0) { 102 log_msg(LOG_DEFAULT, LVL_ERROR, 103 "char_dev_write() returned %d", 104 (int) size); 105 slip_send_pending = 0; 106 break; 107 } 108 written += size; 109 slip_send_pending -= size; 110 } 111 } 112 113 static void write_buffered(async_sess_t *sess, uint8_t ch) 114 { 115 if (slip_send_pending == sizeof(slip_send_buf)) 116 write_flush(sess); 117 slip_send_buf[slip_send_pending++] = ch; 118 } 119 78 120 int slip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu) 79 121 { 122 async_sess_t *sess = (async_sess_t *) srv->arg; 123 uint8_t *data = sdu->data; 124 unsigned i; 125 80 126 log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_send()"); 81 return ENOTSUP; 127 128 /* 129 * Strictly speaking, this is not prescribed by the RFC, but the RFC 130 * suggests to start with sending a SLIP_END byte as a synchronization 131 * measure for dealing with previous possible noise on the line. 132 */ 133 write_buffered(sess, SLIP_END); 134 135 for (i = 0; i < sdu->size; i++) { 136 switch (data[i]) { 137 case SLIP_END: 138 write_buffered(sess, SLIP_ESC); 139 write_buffered(sess, SLIP_ESC_END); 140 break; 141 case SLIP_ESC: 142 write_buffered(sess, SLIP_ESC); 143 write_buffered(sess, SLIP_ESC_ESC); 144 break; 145 default: 146 write_buffered(sess, data[i]); 147 break; 148 } 149 } 150 write_buffered(sess, SLIP_END); 151 write_flush(sess); 152 153 return EOK; 82 154 } 83 155 … … 110 182 log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_client_conn()"); 111 183 iplink_conn(iid, icall, &slip_iplink); 184 } 185 186 static uint8_t read_buffered(async_sess_t *sess) 187 { 188 while (slip_recv_pending == 0) { 189 ssize_t size; 190 191 size = char_dev_read(sess, slip_recv_buf, 192 sizeof(slip_recv_buf)); 193 if (size < 0) { 194 log_msg(LOG_DEFAULT, LVL_ERROR, 195 "char_dev_read() returned %d", (int) size); 196 return SLIP_END; 197 } 198 slip_recv_pending = size; 199 slip_recv_read = 0; 200 } 201 slip_recv_pending--; 202 return slip_recv_buf[slip_recv_read++]; 203 } 204 205 static int slip_recv_fibril(void *arg) 206 { 207 async_sess_t *sess = (async_sess_t *) arg; 208 static uint8_t recv_final[SLIP_MTU]; 209 iplink_srv_sdu_t sdu; 210 uint8_t ch; 211 int rc; 212 213 sdu.lsrc.ipv4 = 0; 214 sdu.ldest.ipv4 = 0; 215 sdu.data = recv_final; 216 217 while (true) { 218 for (sdu.size = 0; sdu.size < sizeof(recv_final); /**/) { 219 ch = read_buffered(sess); 220 switch (ch) { 221 case SLIP_END: 222 if (sdu.size == 0) { 223 /* 224 * Discard the empty SLIP datagram. 225 */ 226 break; 227 } 228 goto pass; 229 230 case SLIP_ESC: 231 ch = read_buffered(sess); 232 if (ch == SLIP_ESC_END) { 233 recv_final[sdu.size++] = SLIP_END; 234 break; 235 } else if (ch == SLIP_ESC_ESC) { 236 recv_final[sdu.size++] = SLIP_ESC; 237 break; 238 } 239 240 /* 241 * The RFC suggests to simply insert the wrongly 242 * escaped character into the packet so we fall 243 * through. 244 */ 245 246 default: 247 recv_final[sdu.size++] = ch; 248 break; 249 } 250 251 } 252 253 /* 254 * We have reached the limit of our MTU. Regardless of whether 255 * the datagram is properly ended with SLIP_END, pass it along. 256 * If the next character is really SLIP_END, nothing 257 * catastrophic happens. The algorithm will just see an 258 * artificially empty SLIP datagram and life will go on. 259 */ 260 261 pass: 262 rc = iplink_ev_recv(&slip_iplink, &sdu); 263 if (rc != EOK) { 264 log_msg(LOG_DEFAULT, LVL_ERROR, 265 "iplink_ev_recv() returned %d", rc); 266 } 267 } 268 269 return 0; 112 270 } 113 271 … … 118 276 category_id_t iplinkcid; 119 277 async_sess_t *sess = NULL; 278 fid_t fid; 120 279 int rc; 121 280 … … 147 306 } 148 307 149 sess = loc_service_connect(EXCHANGE_SERIALIZE, svcid, 0); 308 /* 309 * Create a parallel session because we will need to be able to both 310 * read and write from the char_dev. 311 */ 312 sess = loc_service_connect(EXCHANGE_PARALLEL, svcid, 0); 150 313 if (!sess) { 151 314 log_msg(LOG_DEFAULT, LVL_ERROR, … … 154 317 return rc; 155 318 } 319 slip_iplink.arg = sess; 156 320 157 321 rc = loc_service_register(linkstr, &linksid); … … 166 330 if (rc != EOK) { 167 331 log_msg(LOG_DEFAULT, LVL_ERROR, 168 "F iled to add service %d (%s) to category %d (%s).",332 "Failed to add service %d (%s) to category %d (%s).", 169 333 (int) linksid, linkstr, (int) iplinkcid, CAT_IPLINK); 170 334 goto fail; 171 335 } 336 337 fid = fibril_create(slip_recv_fibril, sess); 338 if (!fid) { 339 log_msg(LOG_DEFAULT, LVL_ERROR, 340 "Failed to create receive fibril."); 341 goto fail; 342 } 343 fibril_add_ready(fid); 172 344 173 345 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.