@@ -21,6 +21,12 @@ const (
21
21
22
22
// defaultKeepAlive configures TCP keepalive probe interval on the dialer.
23
23
defaultKeepAlive = 30 * time .Second
24
+
25
+ // defaultReadTimeout sets the maximum time to wait for read operations.
26
+ defaultReadTimeout = 30 * time .Second
27
+
28
+ // defaultWriteTimeout sets the maximum time to wait for write operations.
29
+ defaultWriteTimeout = 30 * time .Second
24
30
)
25
31
26
32
func NewWsmanTCP (cp Parameters ) * Target {
@@ -127,6 +133,11 @@ func (t *Target) Send(data []byte) error {
127
133
return fmt .Errorf ("no active connection" )
128
134
}
129
135
136
+ // Optimize: Only set deadline if enough time has passed or it's not set
137
+ if err := t .setWriteDeadlineIfNeeded (); err != nil {
138
+ return fmt .Errorf ("failed to set write deadline: %w" , err )
139
+ }
140
+
130
141
_ , err := t .conn .Write (data )
131
142
if err != nil {
132
143
return fmt .Errorf ("failed to send data: %w" , err )
@@ -141,6 +152,11 @@ func (t *Target) Receive() ([]byte, error) {
141
152
return nil , fmt .Errorf ("no active connection" )
142
153
}
143
154
155
+ // Optimize: Only set deadline if enough time has passed or it's not set
156
+ if err := t .setReadDeadlineIfNeeded (); err != nil {
157
+ return nil , fmt .Errorf ("failed to set read deadline: %w" , err )
158
+ }
159
+
144
160
tmp := t .bufferPool .Get ().([]byte )
145
161
defer t .bufferPool .Put (tmp ) //nolint:staticcheck // changing the argument to be pointer-like to avoid allocations caused issues.
146
162
@@ -152,6 +168,48 @@ func (t *Target) Receive() ([]byte, error) {
152
168
return append ([]byte (nil ), tmp [:n ]... ), nil
153
169
}
154
170
171
+ // setReadDeadlineIfNeeded sets read deadline only when needed to reduce syscall overhead
172
+ func (t * Target ) setReadDeadlineIfNeeded () error {
173
+ t .deadlineMutex .Lock ()
174
+ defer t .deadlineMutex .Unlock ()
175
+
176
+ now := time .Now ()
177
+ // Only set deadline if it's been more than half the timeout period since last set
178
+ // or if it's never been set (zero value)
179
+ const deadlineRefreshInterval = defaultReadTimeout / 2
180
+
181
+ if t .lastReadDeadlineSet .IsZero () || now .Sub (t .lastReadDeadlineSet ) > deadlineRefreshInterval {
182
+ newDeadline := now .Add (defaultReadTimeout )
183
+ if err := t .conn .SetReadDeadline (newDeadline ); err != nil {
184
+ return err
185
+ }
186
+ t .lastReadDeadlineSet = now
187
+ }
188
+
189
+ return nil
190
+ }
191
+
192
+ // setWriteDeadlineIfNeeded sets write deadline only when needed to reduce syscall overhead
193
+ func (t * Target ) setWriteDeadlineIfNeeded () error {
194
+ t .deadlineMutex .Lock ()
195
+ defer t .deadlineMutex .Unlock ()
196
+
197
+ now := time .Now ()
198
+ // Only set deadline if it's been more than half the timeout period since last set
199
+ // or if it's never been set (zero value)
200
+ const deadlineRefreshInterval = defaultWriteTimeout / 2
201
+
202
+ if t .lastWriteDeadlineSet .IsZero () || now .Sub (t .lastWriteDeadlineSet ) > deadlineRefreshInterval {
203
+ newDeadline := now .Add (defaultWriteTimeout )
204
+ if err := t .conn .SetWriteDeadline (newDeadline ); err != nil {
205
+ return err
206
+ }
207
+ t .lastWriteDeadlineSet = now
208
+ }
209
+
210
+ return nil
211
+ }
212
+
155
213
// CloseConnection cleanly closes the TCP connection.
156
214
func (t * Target ) CloseConnection () error {
157
215
if t .conn == nil {
@@ -164,6 +222,12 @@ func (t *Target) CloseConnection() error {
164
222
}
165
223
166
224
t .conn = nil
225
+
226
+ // Reset deadline tracking when connection is closed
227
+ t .deadlineMutex .Lock ()
228
+ t .lastReadDeadlineSet = time.Time {}
229
+ t .lastWriteDeadlineSet = time.Time {}
230
+ t .deadlineMutex .Unlock ()
167
231
168
232
return nil
169
233
}
0 commit comments