-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrimaryHDLCDataLink.java
More file actions
221 lines (202 loc) · 7.6 KB
/
PrimaryHDLCDataLink.java
File metadata and controls
221 lines (202 loc) · 7.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import java.io.IOException;
// Data Link Layer Entity for Primary Station
// Uses the HDLC protocol for communication over a multipoint link
// Assumptions
// Normal Response Mode operation over multi-point link (simulated using PhysicalLayer class over Sockets)
// Use 3-bit sequence numbers
// Not Supported:
// FSC checking
// Bit stuffing (frames are transmitted as strings)
// Flag = "01111110"
// Frames implemented:
// Command Frames: SNRM, DISC
// Response Frames: UA
// Command/Response Frames: I, RR
public class PrimaryHDLCDataLink
{
// Private instance variables
private final int MAX = 5; // Maximum number of supported connections
private PhysicalLayer physicalLayer; // for sending/receiving frames
// Data for multiple connections in the case of the primary station
// For the secondary station, used values at index 0
private int [] adrs = new int [MAX];
private int [] vs = new int [MAX];
private int [] vr = new int [MAX];
// Constructor
public PrimaryHDLCDataLink()
{
physicalLayer = new PhysicalLayer();
}
public void close() throws IOException
{
physicalLayer.close();
}
/*----------------------------------------------------------
* Connection Service
*-----------------------------------------------------------*/
// This is a confirmed service, i.e. the return value reflects results from the confirmation
// Method: dlConnecRequest
// Establishes connection to station at address adr
// Sends SNRM with Poll bit set to 1
public Result dlConnectRequest(int adr)
{
Result.ResultCode cd = Result.ResultCode.SrvSucessful;
int secondaryId = getFreeSecondaryId();
// Check if room for additional connection
if(secondaryId == -1)
cd = Result.ResultCode.ReachedLimit;
else
{
String frame = HdlcDefs.FLAG+BitString.intToBitString(adr,HdlcDefs.ADR_SIZE_BITS)+
HdlcDefs.U_FRAME+
HdlcDefs.SNRM_M1+HdlcDefs.P1+HdlcDefs.SNRM_M2+
HdlcDefs.FLAG;
System.out.println("Data Link Layer: prepared SNRM frame >"+BitString.displayFrame(frame)+"<");
physicalLayer.transmit(frame);
adrs[secondaryId] = adr;
vs[secondaryId]=0;
vr[secondaryId]=0;
}
return(new Result(cd, adr, null));
}
// Method: dlConnecConfirmation
// Confirms connection
// Receives UA with F bit set to 1, extract address
public Result dlConnectConfirmation()
{
Result.ResultCode cd = Result.ResultCode.SrvSucessful;
int adr = 0;
String retStr = null;
// Wait for UA response frame
String frame = physicalLayer.receive();
adr = BitString.bitStringToInt(frame.substring(HdlcDefs.ADR_START,HdlcDefs.ADR_END));
// Check if frame is U-frame
String type = frame.substring(HdlcDefs.TYPE_START, HdlcDefs.TYPE_END);
if(type.equals(HdlcDefs.U_FRAME) == false)
{
cd = Result.ResultCode.UnexpectedFrameReceived;
adr = BitString.bitStringToInt(frame.substring(HdlcDefs.ADR_START,HdlcDefs.ADR_END));
retStr = type;
}
else
{
String mBits = frame.substring(HdlcDefs.M1_START, HdlcDefs.M1_END) +
frame.substring(HdlcDefs.M2_START, HdlcDefs.M2_END);
if(mBits.equals(HdlcDefs.UA)==false)
{
cd = Result.ResultCode.UnexpectedUFrameReceived;
retStr = mBits;
}
else if(getSecondaryId(adr) == -1)
{
cd = Result.ResultCode.InvalidAddress;
}
else System.out.println("Data Link Layer: received UA frame >"+BitString.displayFrame(frame)+"<");
}
return(new Result(cd, adr, retStr));
}
/*----------------------------------------------------------
* Disconnect service - non-confirmed service
*-----------------------------------------------------------*/
// Data disconnection service - non-confirmed service
public Result dlDisconnectRequest(int adr)
{ // Disconnection by Primary.
Result.ResultCode cd = Result.ResultCode.SrvSucessful;
int secondaryId = this.getSecondaryId(adr); // find the id
if(secondaryId == -1)
{
cd = Result.ResultCode.InvalidAddress;
}
else
{
// Send DISC frame
String frame = HdlcDefs.FLAG+BitString.intToBitString(adr,HdlcDefs.ADR_SIZE_BITS)+
HdlcDefs.U_FRAME+
HdlcDefs.DISC_M1+HdlcDefs.P0+HdlcDefs.DISC_M2+
HdlcDefs.FLAG;
System.out.println("Data Link Layer: prepared DISC frame >"+BitString.displayFrame(frame)+"<");
physicalLayer.transmit(frame);
adrs[secondaryId] = 0;
}
return(new Result(cd, adr, null));
}
/*----------------------------------------------------------
* Data service - non-confirmed service
*-----------------------------------------------------------*/
// Returns null if no data received
public Result dlDataIndication(int adr)
{
// Some vriable declarations;
int id; // identifier of the station (for indexing into adrs, vs, vr
int ns; // ns found in information frame
Result.ResultCode cd = Result.ResultCode.SrvSucessful;
String frame; // For referencing frames
String sdu = ""; // for building return string
String data; // for getting data field from information frame
// The primary polls secondary at address to
// get secondary to send data.
id = this.getSecondaryId(adr);
if(id == -1)
{
cd = Result.ResultCode.InvalidAddress;
return(new Result(cd,adr,null));
}
// address is valid
// Send the poll (an RR with the P bit set
frame = HdlcDefs.FLAG+BitString.intToBitString(adr,HdlcDefs.ADR_SIZE_BITS)+
HdlcDefs.S_FRAME+HdlcDefs.RR_SS+HdlcDefs.P1+
BitString.intToBitString(vr[adr], HdlcDefs.SNUM_SIZE_BITS)+
HdlcDefs.FLAG;
System.out.println("Data Link Layer: sending RR frame (poll) >"+BitString.displayFrame(frame)+"<");
physicalLayer.transmit(frame);
// Collect the data in the received frames - ack each frame (go back N)
boolean flag = true;
while(flag)
{
frame = physicalLayer.receive();
if(frame.charAt(HdlcDefs.TYPE_START) == '0') // Ignore other frames
{
ns = BitString.bitStringToInt(frame.substring(HdlcDefs.NS_START,HdlcDefs.NS_END));
if(ns == vr[id]) // Is it the expected frame
{
data = frame.substring(HdlcDefs.DATA_START, frame.length()-HdlcDefs.FLAG_SIZE_BITS);
sdu = sdu+BitString.bitStringToString(data);
vr[id] = (vr[id]+1)%HdlcDefs.SNUM_SIZE_COUNT; // increment next expected seq num
if(frame.charAt(HdlcDefs.PF_IX) == '1') flag = false; // last frame of data - stop
System.out.println("Data Link Layer: received I frame >"+BitString.displayFrame(frame)+"<");
}
// Send acknowledgement even if frame not expected
frame = HdlcDefs.FLAG+BitString.intToBitString(adr,HdlcDefs.ADR_SIZE_BITS)+
HdlcDefs.S_FRAME+HdlcDefs.RR_SS+HdlcDefs.P0+
BitString.intToBitString(vr[id], HdlcDefs.SNUM_SIZE_BITS)+
HdlcDefs.FLAG;
System.out.println("Data Link Layer: prepared RR frame(ack) >"+BitString.displayFrame(frame)+"<");
physicalLayer.transmit(frame);
}
}
return(new Result(cd, adr, sdu));
}
/*------------------------------------------------------------------------
* Helper Methods
*------------------------------------------------------------------------*/
// Finds the index in the adrs array that is free (=0).
private int getFreeSecondaryId()
{
int id = -1;
for(int ix=0 ; ix < MAX && id == -1; ix++)
{
if(adrs[ix] == 0) id = ix;
}
return(id);
}
// Finds the index in the adrs array for a given address.
private int getSecondaryId(int adr)
{
int id = -1;
for(int ix=0 ; ix < MAX && id == -1; ix++)
{
if(adrs[ix] == adr) id = ix;
}
return(id);
}
}