Source code: com/act365/net/tcp/TCPWriter.java
1 /*
2 * JSocket Wrench
3 *
4 * Copyright (C) act365.com October 2003
5 *
6 * Web site: http://www.act365.com/wrench
7 * E-mail: developers@act365.com
8 *
9 * The JSocket Wrench library adds support for low-level Internet protocols
10 * to the Java programming language.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
20 * Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 package com.act365.net.tcp ;
28
29 import com.act365.net.* ;
30
31 /**
32 * Writes TCP messages to a bytestream.
33 */
34
35 public class TCPWriter {
36
37 static byte[] write( TCPMessage message ){
38
39 int length = 20 + message.options.length + message.data.length ;
40
41 byte[] buffer = new byte[ length ];
42
43 SocketUtils.shortToBytes( message.sourceport , buffer , 0 );
44 SocketUtils.shortToBytes( message.destinationport , buffer , 2 );
45 SocketUtils.intToBytes( message.sequencenumber , buffer , 4 );
46 SocketUtils.intToBytes( message.acknowledgementnumber , buffer , 8 );
47
48 buffer[ 12 ] = (byte)( message.headerlength << 4 );
49 buffer[ 13 ] = 0 ;
50
51 if( message.urg ) buffer[ 13 ] |= TCP.URG ;
52 if( message.ack ) buffer[ 13 ] |= TCP.ACK ;
53 if( message.psh ) buffer[ 13 ] |= TCP.PSH ;
54 if( message.rst ) buffer[ 13 ] |= TCP.RST ;
55 if( message.syn ) buffer[ 13 ] |= TCP.SYN ;
56 if( message.fin ) buffer[ 13 ] |= TCP.FIN ;
57
58 SocketUtils.shortToBytes( message.windowsize , buffer , 14 );
59 SocketUtils.shortToBytes( message.checksum , buffer , 16 );
60 SocketUtils.shortToBytes( message.urgentpointer , buffer , 18 );
61
62 int i = 20 ;
63
64 while( i < 20 + message.options.length ){
65 buffer[ i ] = message.options[ i - 20 ];
66 ++ i ;
67 }
68
69 while( i < length ){
70 buffer[ i ] = message.data[ i - 20 - message.options.length ];
71 ++ i ;
72 }
73
74 return buffer ;
75 }
76
77 /**
78 * Writes a TCP message to a bytestream.
79 */
80
81 public static byte[] write( byte[] sourceaddress ,
82 short sourceport ,
83 byte[] destinationaddress ,
84 short destinationport ,
85 int sequencenumber ,
86 int acknowledgementnumber ,
87 boolean ack ,
88 boolean rst ,
89 boolean syn ,
90 boolean fin ,
91 boolean psh ,
92 short windowsize ,
93 TCPOptions options ,
94 byte[] data ,
95 int offset ,
96 int count ){
97
98 TCPMessage message = new TCPMessage();
99
100 message.sourceport = sourceport ;
101 message.destinationport = destinationport ;
102 message.sequencenumber = sequencenumber ;
103 message.acknowledgementnumber = acknowledgementnumber ;
104 message.headerlength = 5 ;
105 message.urg = false ;
106 message.ack = ack ;
107 message.psh = psh ;
108 message.rst = rst ;
109 message.syn = syn ;
110 message.fin = fin ;
111 message.windowsize = windowsize ;
112 message.checksum = 0 ;
113 message.urgentpointer = 0 ;
114
115 byte[] optionsbuffer = new byte[ 128 ];
116
117 int cursor = 0 ;
118
119 if( options.isMaxSegmentSizeSet() ){
120 optionsbuffer[ cursor ] = 2 ;
121 optionsbuffer[ cursor + 1 ] = 4 ;
122 SocketUtils.shortToBytes( options.getMaxSegmentSize() , optionsbuffer , cursor + 2 );
123 cursor += 4 ;
124 }
125
126 if( options.isWindowScaleFactorSet() ){
127 optionsbuffer[ cursor ] = 1 ;
128 optionsbuffer[ cursor + 1 ] = 3 ;
129 optionsbuffer[ cursor + 2 ] = 3 ;
130 optionsbuffer[ cursor + 3 ] = options.getWindowScaleFactor() ;
131 cursor += 4 ;
132 }
133
134 if( options.isTimestampSet() ){
135 optionsbuffer[ cursor ] = 1 ;
136 optionsbuffer[ cursor + 1 ] = 1 ;
137 optionsbuffer[ cursor + 2 ] = 8 ;
138 optionsbuffer[ cursor + 3 ] = 10 ;
139 SocketUtils.intToBytes( options.getTimestampValue() , optionsbuffer , cursor + 4 );
140 SocketUtils.intToBytes( options.getTimestampEchoReply() , optionsbuffer , cursor + 8 );
141 cursor += 12 ;
142 }
143
144 message.headerlength += cursor / 4 ;
145 message.options = new byte[ cursor ];
146
147 int i = -1 ;
148
149 while( ++ i < cursor ){
150 message.options[ i ] = optionsbuffer[ i ];
151 }
152
153 message.data = new byte[ count ];
154
155 i = -1 ;
156
157 while( ++ i < count ){
158 message.data[ i ] = data[ i + offset ];
159 }
160
161 short length = (short)( 4 * message.headerlength + count );
162
163 message.checksum = SocketUtils.checksum( sourceaddress ,
164 destinationaddress ,
165 (byte) SocketConstants.IPPROTO_TCP ,
166 length ,
167 write( message ) ,
168 0 );
169
170 return write( message );
171 }
172 }
173