[4332] | 1 | %------------------------------------------------------------------------- |
---|
| 2 | % WARPLab Framework |
---|
[2149] | 3 | % |
---|
[4332] | 4 | % Copyright 2013, Mango Communications. All rights reserved. |
---|
| 5 | % Distributed under the WARP license (http://warpproject.org/license) |
---|
[2149] | 6 | % |
---|
[4332] | 7 | % Chris Hunter (chunter [at] mangocomm.com) |
---|
| 8 | % Patrick Murphy (murphpo [at] mangocomm.com) |
---|
| 9 | % Erik Welsh (welsh [at] mangocomm.com) |
---|
| 10 | %------------------------------------------------------------------------- |
---|
[2149] | 11 | |
---|
[1989] | 12 | classdef wl_transport_eth_udp_java < wl_transport & handle_light |
---|
[2149] | 13 | % Java-based Ethernet UDP Transport for unicast traffic |
---|
[1975] | 14 | % User code should not use this object directly-- the parent wl_node will |
---|
| 15 | % instantiate the appropriate transport object for the hardware in use |
---|
[2149] | 16 | |
---|
| 17 | %******************************** Properties ********************************** |
---|
| 18 | |
---|
[1915] | 19 | properties (SetAccess = public) |
---|
[4416] | 20 | timeout; % Maximum time spent waiting before retransmission |
---|
[1915] | 21 | end |
---|
[2149] | 22 | |
---|
[1915] | 23 | properties (SetAccess = protected, Hidden = true) |
---|
[4416] | 24 | sock; % UDP socket |
---|
| 25 | |
---|
| 26 | j_address; % Java address (statically allocated for performance reasons) |
---|
| 27 | send_pkt; % DatagramPacket (statically allocated for performance reasons) |
---|
| 28 | recv_pkt; % DatagramPacket (statically allocated for performance reasons) |
---|
| 29 | |
---|
| 30 | status; % Status of UDP socket |
---|
| 31 | maxPayload; % Maximum payload size (e.g. MTU - ETH/IP/UDP headers) |
---|
[1915] | 32 | end |
---|
[2149] | 33 | |
---|
[4416] | 34 | properties (SetAccess = protected) |
---|
| 35 | address; % IP address of destination |
---|
| 36 | port; % Port of destination |
---|
| 37 | end |
---|
| 38 | |
---|
[1915] | 39 | properties (SetAccess = public) |
---|
[4416] | 40 | hdr; % Transport header object |
---|
| 41 | rxBufferSize; % OS's receive buffer size in bytes |
---|
[1915] | 42 | end |
---|
[2149] | 43 | |
---|
[4309] | 44 | properties(Hidden = true, Constant = true) |
---|
| 45 | % These constants define specific command IDs used by this object. |
---|
| 46 | % Their C counterparts are found in wl_transport.h |
---|
[4332] | 47 | GRP = 'transport'; |
---|
| 48 | CMD_PING = 1; % 0x000001 |
---|
[4784] | 49 | CMD_PAYLOADSIZETEST = 2; % 0x000002 |
---|
[2069] | 50 | |
---|
[4784] | 51 | CMD_NODEGRPID_ADD = 16; % 0x000010 |
---|
| 52 | CMD_NODEGRPID_CLEAR = 17; % 0x000011 |
---|
| 53 | |
---|
[4309] | 54 | TRANSPORT_NOT_READY_MAX_RETRY = 50; |
---|
| 55 | TRANSPORT_NOT_READY_WAIT_TIME = 0.1; |
---|
[1948] | 56 | end |
---|
[2149] | 57 | |
---|
| 58 | %********************************* Methods ************************************ |
---|
| 59 | |
---|
[1915] | 60 | methods |
---|
[1931] | 61 | function obj = wl_transport_eth_udp_java() |
---|
[4416] | 62 | import java.net.InetAddress |
---|
| 63 | |
---|
[4332] | 64 | obj.hdr = wl_transport_header; |
---|
[1915] | 65 | obj.hdr.pktType = obj.hdr.PKTTYPE_HTON_MSG; |
---|
[4332] | 66 | obj.status = 0; |
---|
| 67 | obj.timeout = 1; |
---|
[4416] | 68 | obj.maxPayload = 1000; % Sane default. This gets overwritten by CMD_PAYLOADSIZETEST command. |
---|
| 69 | obj.port = 0; |
---|
| 70 | obj.address = '10.0.0.0'; |
---|
| 71 | obj.j_address = InetAddress.getByName(obj.address); |
---|
[4332] | 72 | |
---|
[4416] | 73 | obj.create_internal_pkts(); |
---|
| 74 | |
---|
[1915] | 75 | obj.checkSetup(); |
---|
| 76 | end |
---|
| 77 | |
---|
| 78 | function checkSetup(obj) |
---|
[4332] | 79 | % Currently not implemented |
---|
[1915] | 80 | end |
---|
[2149] | 81 | |
---|
[4818] | 82 | function setMaxPayload(obj, value) |
---|
| 83 | if (isempty(value)) |
---|
| 84 | error('wl_transport_eth_udp_java:setMaxPayload', 'setMaxPayload requires a non-empty argument.'); |
---|
| 85 | else |
---|
| 86 | obj.maxPayload = value; |
---|
| 87 | |
---|
| 88 | % Update the send / recv packets |
---|
| 89 | obj.update_pkt_length(); |
---|
| 90 | end |
---|
[2149] | 91 | end |
---|
| 92 | |
---|
| 93 | function out = getMaxPayload(obj) |
---|
[2856] | 94 | out = double(obj.maxPayload); |
---|
[2149] | 95 | end |
---|
| 96 | |
---|
[4416] | 97 | function setAddress(obj, value) |
---|
| 98 | import java.net.InetAddress |
---|
| 99 | |
---|
| 100 | if(ischar(value)) |
---|
| 101 | obj.address = value; |
---|
| 102 | else |
---|
| 103 | obj.address = obj.int2IP(value); |
---|
| 104 | end |
---|
| 105 | |
---|
| 106 | % Update the java address |
---|
| 107 | obj.j_address = InetAddress.getByName(obj.address); |
---|
| 108 | |
---|
| 109 | % Update the send / recv packets |
---|
| 110 | obj.update_pkt_address(); |
---|
| 111 | end |
---|
| 112 | |
---|
| 113 | function out = getAddress(obj) |
---|
| 114 | out = obj.address; |
---|
| 115 | end |
---|
| 116 | |
---|
| 117 | function setPort(obj, value) |
---|
| 118 | obj.port = value; |
---|
| 119 | |
---|
| 120 | % Update the send / recv packets |
---|
| 121 | obj.update_pkt_port(); |
---|
| 122 | end |
---|
| 123 | |
---|
| 124 | function out = getPort(obj) |
---|
| 125 | out = obj.port; |
---|
| 126 | end |
---|
| 127 | |
---|
[4332] | 128 | function open(obj, varargin) |
---|
| 129 | % varargin{1}: (optional) IP address |
---|
| 130 | % varargin{2}: (optional) port |
---|
[1931] | 131 | |
---|
[4332] | 132 | REQUESTED_BUF_SIZE = 2^22; |
---|
| 133 | |
---|
[1931] | 134 | import java.io.* |
---|
| 135 | import java.net.DatagramSocket |
---|
| 136 | import java.net.DatagramPacket |
---|
[4416] | 137 | |
---|
[1915] | 138 | if(nargin==3) |
---|
[4416] | 139 | obj.setAddress(varargin{1}); |
---|
| 140 | obj.setPort(varargin{2}); |
---|
[1915] | 141 | end |
---|
[1931] | 142 | |
---|
[1944] | 143 | obj.sock = DatagramSocket(); |
---|
[4332] | 144 | |
---|
[1931] | 145 | obj.sock.setSoTimeout(1); |
---|
| 146 | obj.sock.setReuseAddress(1); |
---|
[4332] | 147 | obj.sock.setBroadcast(true); |
---|
| 148 | obj.sock.setSendBufferSize(REQUESTED_BUF_SIZE); |
---|
[1961] | 149 | obj.sock.setReceiveBufferSize(REQUESTED_BUF_SIZE); |
---|
[4332] | 150 | |
---|
[1952] | 151 | x = obj.sock.getReceiveBufferSize(); |
---|
[4332] | 152 | |
---|
[1961] | 153 | if(x < REQUESTED_BUF_SIZE) |
---|
[1952] | 154 | fprintf('OS reduced recv buffer size to %d\n', x); |
---|
| 155 | end |
---|
[4332] | 156 | |
---|
| 157 | obj.rxBufferSize = x; |
---|
| 158 | obj.status = 1; |
---|
[1915] | 159 | end |
---|
| 160 | |
---|
[4332] | 161 | function out = procCmd(obj, nodeInd, node, cmdStr, varargin) |
---|
| 162 | % wl_node procCmd(obj, nodeInd, node, varargin) |
---|
| 163 | % obj: Node object (when called using dot notation) |
---|
| 164 | % nodeInd: Index of the current node, when wl_node is iterating over nodes |
---|
| 165 | % node: Current node object |
---|
| 166 | % cmdStr: Command string of the interface command |
---|
| 167 | % varargin: |
---|
| 168 | % [1:N} Command arguments |
---|
| 169 | % |
---|
| 170 | out = []; |
---|
| 171 | |
---|
[1915] | 172 | cmdStr = lower(cmdStr); |
---|
| 173 | switch(cmdStr) |
---|
[4332] | 174 | |
---|
| 175 | %--------------------------------------------------------- |
---|
[1915] | 176 | case 'ping' |
---|
[1975] | 177 | % Test to make sure node can be accessed via this |
---|
| 178 | % transport |
---|
[1915] | 179 | % |
---|
| 180 | % Arguments: none |
---|
| 181 | % Returns: true if board responds; raises error otherwise |
---|
[4332] | 182 | % |
---|
[1948] | 183 | myCmd = wl_cmd(node.calcCmd(obj.GRP,obj.CMD_PING)); |
---|
[1975] | 184 | node.sendCmd(myCmd); |
---|
[1915] | 185 | out = true; %sendCmd will timeout and raise error if board doesn't respond |
---|
[2069] | 186 | |
---|
[4332] | 187 | %--------------------------------------------------------- |
---|
[1964] | 188 | case 'payload_size_test' |
---|
[4332] | 189 | % Determine objects maxPayload parameter |
---|
[1975] | 190 | % |
---|
| 191 | % Arguments: none |
---|
[1997] | 192 | % Returns: none |
---|
[4332] | 193 | % |
---|
| 194 | configFile = which('wl_config.ini'); |
---|
[1977] | 195 | |
---|
[1997] | 196 | if(isempty(configFile)) |
---|
[2865] | 197 | error('cannot find wl_config.ini. please run wl_setup.m'); |
---|
[1997] | 198 | end |
---|
[4332] | 199 | |
---|
[4375] | 200 | readKeys = {'network', '', 'max_transport_payload_size', ''}; |
---|
| 201 | max_transport_payload_size = inifile(configFile, 'read', readKeys); |
---|
| 202 | max_transport_payload_size = str2num(max_transport_payload_size{1}); |
---|
[1997] | 203 | |
---|
[4375] | 204 | % Determine the payloads to test |
---|
| 205 | payloadTestSizes = []; |
---|
| 206 | |
---|
| 207 | for i = [1000 1470 5000 8966] |
---|
| 208 | if (i < max_transport_payload_size) |
---|
| 209 | payloadTestSizes = [payloadTestSizes, i]; |
---|
| 210 | end |
---|
[1997] | 211 | end |
---|
| 212 | |
---|
[4375] | 213 | payloadTestSizes = [payloadTestSizes, max_transport_payload_size]; |
---|
| 214 | |
---|
[4386] | 215 | % WARPLab Header is (see http://warpproject.org/trac/wiki/WARPLab/Reference/Architecture/WireFormat ): |
---|
| 216 | % - 2 byte pad |
---|
| 217 | % - Transport header |
---|
| 218 | % - Command header |
---|
| 219 | payloadTestSizes = floor((payloadTestSizes - (sizeof(node.transport.hdr) + sizeof(wl_cmd) + 2)) / 4); |
---|
| 220 | |
---|
[1977] | 221 | for index = 1:length(payloadTestSizes) |
---|
[4386] | 222 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_PAYLOADSIZETEST)); |
---|
[1977] | 223 | myCmd.addArgs(1:payloadTestSizes(index)); |
---|
[1997] | 224 | try |
---|
| 225 | resp = node.sendCmd(myCmd); |
---|
[2149] | 226 | obj.setMaxPayload( resp.getArgs ); |
---|
[4375] | 227 | if(obj.getMaxPayload < (payloadTestSizes(index) * 4)) |
---|
[1997] | 228 | break; |
---|
| 229 | end |
---|
| 230 | catch ME |
---|
| 231 | break |
---|
[1977] | 232 | end |
---|
| 233 | end |
---|
[2069] | 234 | |
---|
[4332] | 235 | %--------------------------------------------------------- |
---|
[2041] | 236 | case 'add_node_group_id' |
---|
| 237 | % Adds a Node Group ID to the node so that it can |
---|
| 238 | % process broadcast commands that are received from |
---|
| 239 | % that node group. |
---|
| 240 | % |
---|
| 241 | % Arguments: (uint32 NODE_GRP_ID) |
---|
| 242 | % Returns: none |
---|
| 243 | % |
---|
| 244 | % NODE_GRP_ID: ID provided by wl_node_grp |
---|
[4332] | 245 | % |
---|
| 246 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_NODEGRPID_ADD)); |
---|
| 247 | myCmd.addArgs(varargin{1}); |
---|
[2041] | 248 | node.sendCmd(myCmd); |
---|
[2069] | 249 | |
---|
[4332] | 250 | %--------------------------------------------------------- |
---|
[2041] | 251 | case 'clear_node_group_id' |
---|
| 252 | % Clears a Node Group ID from the node so it can ignore |
---|
| 253 | % broadcast commands that are received from that node |
---|
| 254 | % group. |
---|
| 255 | % |
---|
| 256 | % Arguments: (uint32 NODE_GRP_ID) |
---|
| 257 | % Returns: none |
---|
| 258 | % |
---|
| 259 | % NODE_GRP_ID: ID provided by wl_node_grp |
---|
[4332] | 260 | % |
---|
| 261 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_NODEGRPID_CLEAR)); |
---|
| 262 | myCmd.addArgs(varargin{1}); |
---|
[2041] | 263 | node.sendCmd(myCmd); |
---|
[2055] | 264 | |
---|
[4332] | 265 | %--------------------------------------------------------- |
---|
[1915] | 266 | otherwise |
---|
[2865] | 267 | error('unknown command ''%s''',cmdStr); |
---|
[1915] | 268 | end |
---|
| 269 | |
---|
[4332] | 270 | if((iscell(out) == 0) && (numel(out) ~= 1)) |
---|
[1915] | 271 | out = {out}; |
---|
| 272 | end |
---|
| 273 | end |
---|
| 274 | |
---|
| 275 | function close(obj) |
---|
[1935] | 276 | if(~isempty(obj.sock)) |
---|
| 277 | try |
---|
| 278 | obj.sock.close(); |
---|
| 279 | catch closeError |
---|
[2865] | 280 | warning( 'Error closing socket; java error was %s', closeError.message) |
---|
[1935] | 281 | end |
---|
[1931] | 282 | end |
---|
| 283 | obj.status=0; |
---|
[1915] | 284 | end |
---|
[2149] | 285 | |
---|
[1915] | 286 | function delete(obj) |
---|
| 287 | obj.close(); |
---|
| 288 | end |
---|
[2149] | 289 | |
---|
[1915] | 290 | function flush(obj) |
---|
[4332] | 291 | % Currently not implemented |
---|
[1915] | 292 | end |
---|
[4332] | 293 | end % methods |
---|
[2149] | 294 | |
---|
[1915] | 295 | methods (Hidden = true) |
---|
[4309] | 296 | function reply = send(obj, send_data, response, varargin) |
---|
| 297 | % send_data : Data to be sent to the node |
---|
| 298 | % response : Does the transmission require a response from the node |
---|
| 299 | % varargin{1}: (optional) |
---|
| 300 | % - increment the transport header; defaults to true if not specified |
---|
| 301 | % |
---|
[1931] | 302 | import java.io.* |
---|
| 303 | import java.net.DatagramSocket |
---|
| 304 | import java.net.DatagramPacket |
---|
| 305 | |
---|
[4309] | 306 | % Initialize variables |
---|
| 307 | maxAttempts = 2; % Maximum times the transport will re-try a packet |
---|
| 308 | payload = uint32(send_data); % Change data to 32 bit unsigned integers for transmit |
---|
| 309 | obj.hdr.msgLength = ((length(payload)) * 4); % Length in bytes (4 bytes / sample) |
---|
| 310 | reply = []; % Initialize array for response from the node |
---|
| 311 | robust = response; |
---|
| 312 | |
---|
| 313 | % Process command line arguments |
---|
| 314 | increment_hdr = true; |
---|
| 315 | |
---|
| 316 | if (nargin == 4) |
---|
| 317 | increment_hdr = varargin{1}; |
---|
[1915] | 318 | end |
---|
| 319 | |
---|
[4309] | 320 | % Set the appropriate flags in the header |
---|
[1915] | 321 | if(robust) |
---|
[4309] | 322 | obj.hdr.flags = bitset(obj.hdr.flags, 1, 1); |
---|
[1915] | 323 | else |
---|
[4309] | 324 | obj.hdr.flags = bitset(obj.hdr.flags, 1, 0); |
---|
[1915] | 325 | end |
---|
[4309] | 326 | |
---|
| 327 | % Increment the header and serialize all the data into a uint32 array |
---|
| 328 | if (increment_hdr) |
---|
| 329 | obj.hdr.increment; |
---|
| 330 | end |
---|
[1915] | 331 | |
---|
[4309] | 332 | % Format the data / address arguments for transmission |
---|
| 333 | data = [obj.hdr.serialize, payload]; % Get a unified array with the header and data |
---|
| 334 | data8 = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)), 'uint8')]; % Change to uint8 and pad by 2 bytes so payload is 32 bit aligned w/ Eth header |
---|
[4416] | 335 | |
---|
| 336 | pkt_send = obj.send_pkt; % Get pointer to statically allocated packet |
---|
| 337 | pkt_send.setData(data8, 0, length(data8)); % Update the send packet with the correct data |
---|
| 338 | % pkt_send = DatagramPacket(data8, length(data8), obj.j_address, obj.port); % Create a java DatagramPacket to send over the network |
---|
[1931] | 339 | |
---|
[4309] | 340 | % Send the packet |
---|
[1931] | 341 | obj.sock.send(pkt_send); |
---|
[1915] | 342 | |
---|
[4309] | 343 | % Wait to receive reply from the board |
---|
| 344 | if(robust == 1) |
---|
| 345 | hdr_length = obj.hdr.length; |
---|
[4416] | 346 | pkt_recv = obj.recv_pkt; |
---|
[4309] | 347 | currTx = 1; |
---|
| 348 | numWaitRetries = 0; |
---|
[1915] | 349 | receivedResponse = 0; |
---|
[4309] | 350 | currTime = tic; |
---|
[1931] | 351 | |
---|
| 352 | while (receivedResponse == 0) |
---|
| 353 | try |
---|
| 354 | obj.sock.receive(pkt_recv); |
---|
| 355 | recv_len = pkt_recv.getLength; |
---|
| 356 | catch receiveError |
---|
| 357 | if ~isempty(strfind(receiveError.message,'java.net.SocketTimeoutException')) |
---|
[4309] | 358 | % Timeout receiving; do nothing |
---|
[1931] | 359 | recv_len = 0; |
---|
| 360 | else |
---|
[4309] | 361 | fprintf('%s.m--Failed to receive UDP packet.\nJava error message follows:\n%s',mfilename,receiveError.message); |
---|
[1931] | 362 | end |
---|
| 363 | end |
---|
[1915] | 364 | |
---|
[4309] | 365 | % If we have a packet, then process the contents |
---|
[1931] | 366 | if(recv_len > 0) |
---|
| 367 | recv_data8 = pkt_recv.getData; |
---|
[4309] | 368 | reply8 = [recv_data8(3:recv_len) zeros(mod(-(recv_len - 2), 4), 1, 'int8')].'; |
---|
| 369 | reply = swapbytes(typecast(reply8, 'uint32')); |
---|
| 370 | |
---|
| 371 | % Check the header to see if this was a valid reply |
---|
| 372 | if(obj.hdr.isReply(reply(1:hdr_length))) |
---|
| 373 | |
---|
| 374 | % Check the header to see if we need to wait for the node to be ready |
---|
| 375 | if ( obj.hdr.isNodeReady(reply(1:hdr_length)) ) |
---|
| 376 | |
---|
| 377 | % Strip off transport header to give response to caller |
---|
| 378 | reply = reply((hdr_length + 1):end); |
---|
| 379 | |
---|
| 380 | if(isempty(reply)) |
---|
| 381 | reply = []; |
---|
| 382 | end |
---|
| 383 | |
---|
| 384 | receivedResponse = 1; |
---|
| 385 | |
---|
| 386 | else |
---|
| 387 | % Node is not ready; Wait and try again |
---|
| 388 | pause( obj.TRANSPORT_NOT_READY_WAIT_TIME ); |
---|
| 389 | numWaitRetries = numWaitRetries + 1; |
---|
| 390 | |
---|
| 391 | % Send packet packet again |
---|
| 392 | obj.sock.send(pkt_send); |
---|
| 393 | |
---|
| 394 | % Check that we have not spent a "long time" waiting for samples to be ready |
---|
| 395 | if ( numWaitRetries > obj.TRANSPORT_NOT_READY_MAX_RETRY ) |
---|
| 396 | error('wl_transport_eth_java:send:isReady', 'Error: Timeout waiting for node to be ready. Please check the node operation.'); |
---|
| 397 | end |
---|
| 398 | |
---|
| 399 | reply = []; |
---|
[1915] | 400 | end |
---|
[4309] | 401 | end |
---|
[1915] | 402 | end |
---|
| 403 | |
---|
[4309] | 404 | % Look for timeout |
---|
| 405 | if ((toc(currTime) > obj.timeout) && (receivedResponse == 0)) |
---|
[1982] | 406 | if(currTx == maxAttempts) |
---|
| 407 | error('wl_transport_eth_java:send:noReply','maximum number of retransmissions met without reply from node'); |
---|
| 408 | end |
---|
[4309] | 409 | |
---|
| 410 | % Retry the packet |
---|
[1931] | 411 | obj.sock.send(pkt_send); |
---|
[4309] | 412 | currTx = currTx + 1; |
---|
[1931] | 413 | currTime = tic; |
---|
[4309] | 414 | end |
---|
[1915] | 415 | end |
---|
| 416 | end |
---|
| 417 | end |
---|
| 418 | |
---|
[4416] | 419 | function send_raw(obj, send_data, send_length) |
---|
| 420 | % send_data : Raw data to be sent over the socket |
---|
| 421 | % send_length : Length of data to be sent over the socket |
---|
| 422 | % |
---|
| 423 | import java.io.* |
---|
| 424 | import java.net.DatagramSocket |
---|
| 425 | import java.net.DatagramPacket |
---|
| 426 | |
---|
| 427 | % Format the data / address arguments for transmission |
---|
| 428 | data8 = typecast(send_data, 'uint8'); % Change to uint8 |
---|
| 429 | pkt_send = obj.send_pkt; % Get pointer to statically allocated packet |
---|
| 430 | pkt_send.setData(data8, 0, send_length); % Update the send packet with the correct data |
---|
| 431 | |
---|
| 432 | % Send the packet |
---|
| 433 | obj.sock.send(pkt_send); |
---|
| 434 | end |
---|
| 435 | |
---|
[4309] | 436 | function resp = receive(obj, varargin) |
---|
| 437 | % Receive all packets from the Ethernet interface and pass array |
---|
| 438 | % of valid responses to the caller. |
---|
| 439 | % |
---|
| 440 | % NOTE: This function will strip off the transport header from the responses |
---|
| 441 | % NOTE: This function is non-blocking and will return an empty response if |
---|
| 442 | % there are no packets available. |
---|
| 443 | % |
---|
[1931] | 444 | import java.io.* |
---|
| 445 | import java.net.DatagramSocket |
---|
| 446 | import java.net.DatagramPacket |
---|
[4309] | 447 | |
---|
| 448 | % Initialize variables |
---|
| 449 | hdr_length = obj.hdr.length; |
---|
[4416] | 450 | pkt_recv = obj.recv_pkt; |
---|
[4309] | 451 | done = false; |
---|
| 452 | resp = []; |
---|
[1931] | 453 | |
---|
[4309] | 454 | % Receive packets |
---|
[1915] | 455 | while ~done |
---|
[1931] | 456 | try |
---|
| 457 | obj.sock.receive(pkt_recv); |
---|
| 458 | recv_len = pkt_recv.getLength; |
---|
| 459 | catch receiveError |
---|
| 460 | if ~isempty(strfind(receiveError.message,'java.net.SocketTimeoutException')) |
---|
[4309] | 461 | % Timeout receiving; do nothing |
---|
[1931] | 462 | recv_len = 0; |
---|
| 463 | else |
---|
| 464 | fprintf('%s.m--Failed to receive UDP packet.\nJava error message follows:\n%s',mfilename,receiveError.message); |
---|
[1915] | 465 | end |
---|
[1931] | 466 | end |
---|
| 467 | |
---|
[4309] | 468 | % If we have a packet, then process the contents |
---|
[1931] | 469 | if(recv_len > 0) |
---|
[4309] | 470 | recv_data8 = pkt_recv.getData; |
---|
| 471 | reply8 = [recv_data8(3:recv_len) zeros(mod(-(recv_len - 2), 4), 1, 'int8')].'; |
---|
| 472 | reply = swapbytes(typecast(reply8, 'uint32')); |
---|
| 473 | |
---|
| 474 | if(obj.hdr.isReply(reply(1:hdr_length))) |
---|
| 475 | % Strip off transport header to give response to caller |
---|
| 476 | reply = reply((hdr_length + 1):end); |
---|
| 477 | |
---|
[1931] | 478 | if(isempty(reply)) |
---|
| 479 | reply = []; |
---|
| 480 | end |
---|
[4309] | 481 | |
---|
| 482 | resp = [resp, reply]; |
---|
| 483 | |
---|
| 484 | done = true; |
---|
[1931] | 485 | end |
---|
[1915] | 486 | else |
---|
| 487 | done = true; |
---|
| 488 | end |
---|
| 489 | end |
---|
| 490 | end |
---|
| 491 | |
---|
[4416] | 492 | function [recv_len, data] = receive_raw(obj, varargin) |
---|
| 493 | % Receive raw data from the Ethernet interface |
---|
| 494 | % |
---|
| 495 | |
---|
| 496 | % Initialize variables |
---|
| 497 | pkt_recv = obj.recv_pkt; |
---|
| 498 | data = []; |
---|
| 499 | |
---|
| 500 | % Try to receive a packet |
---|
| 501 | try |
---|
| 502 | obj.sock.receive(pkt_recv); |
---|
| 503 | recv_len = pkt_recv.getLength; |
---|
| 504 | catch receiveError |
---|
| 505 | if ~isempty(strfind(receiveError.message, 'java.net.SocketTimeoutException')) |
---|
| 506 | recv_len = 0; |
---|
| 507 | else |
---|
| 508 | fprintf('%s.m--Failed to receive UDP packet.\nJava error message follows:\n%s', mfilename, receiveError.message); |
---|
| 509 | end |
---|
| 510 | end |
---|
| 511 | |
---|
| 512 | % If we have a packet, then process the contents |
---|
| 513 | if(recv_len > 0) |
---|
| 514 | recv_data8 = pkt_recv.getData; |
---|
| 515 | reply8 = [recv_data8(3:recv_len) zeros(mod(-(recv_len - 2), 4), 1, 'int8')].'; |
---|
| 516 | data = swapbytes(typecast(reply8, 'uint32')); |
---|
| 517 | end |
---|
| 518 | end |
---|
| 519 | |
---|
[1915] | 520 | function dottedIPout = int2IP(obj,intIn) |
---|
| 521 | addrChars(4) = mod(intIn, 2^8); |
---|
| 522 | addrChars(3) = mod(bitshift(intIn, -8), 2^8); |
---|
| 523 | addrChars(2) = mod(bitshift(intIn, -16), 2^8); |
---|
| 524 | addrChars(1) = mod(bitshift(intIn, -24), 2^8); |
---|
[4309] | 525 | dottedIPout = sprintf('%d.%d.%d.%d', addrChars); |
---|
[1915] | 526 | end |
---|
[2149] | 527 | |
---|
[1915] | 528 | function intOut = IP2int(obj,dottedIP) |
---|
| 529 | addrChars = sscanf(dottedIP, '%d.%d.%d.%d')'; |
---|
[4309] | 530 | intOut = 2^0 * addrChars(4) + 2^8 * addrChars(3) + 2^16 * addrChars(2) + 2^24 * addrChars(1); |
---|
[1915] | 531 | end |
---|
[4416] | 532 | |
---|
| 533 | function create_internal_pkts(obj) |
---|
| 534 | import java.io.* |
---|
| 535 | import java.net.DatagramPacket |
---|
| 536 | |
---|
| 537 | send_pkt_len = obj.getMaxPayload(); |
---|
| 538 | send_data = [zeros(1, send_pkt_len, 'int8')]; |
---|
| 539 | obj.send_pkt = DatagramPacket(send_data, send_pkt_len, obj.j_address, obj.port); |
---|
| 540 | |
---|
| 541 | recv_pkt_len = send_pkt_len + 100; |
---|
| 542 | recv_data = [zeros(1, recv_pkt_len, 'int8')]; |
---|
| 543 | obj.recv_pkt = DatagramPacket(recv_data, recv_pkt_len); |
---|
| 544 | end |
---|
| 545 | |
---|
| 546 | function update_pkt_port(obj) |
---|
| 547 | obj.send_pkt.setPort(obj.port); |
---|
| 548 | end |
---|
| 549 | |
---|
| 550 | function update_pkt_address(obj) |
---|
| 551 | obj.send_pkt.setAddress(obj.j_address); |
---|
| 552 | end |
---|
| 553 | |
---|
| 554 | function update_pkt_length(obj) |
---|
| 555 | send_pkt_len = obj.getMaxPayload(); |
---|
| 556 | send_data = zeros(1, send_pkt_len, 'int8'); |
---|
| 557 | obj.send_pkt.setData(send_data); |
---|
| 558 | obj.send_pkt.setLength(send_pkt_len); |
---|
| 559 | |
---|
| 560 | recv_pkt_len = send_pkt_len + 100; |
---|
| 561 | recv_data = zeros(1, recv_pkt_len, 'int8'); |
---|
| 562 | obj.recv_pkt.setData(recv_data); |
---|
| 563 | obj.recv_pkt.setLength(recv_pkt_len); |
---|
| 564 | end |
---|
[1915] | 565 | end |
---|
[4332] | 566 | end % classdef |
---|