2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Paweł Dziepak, pdziepak@quarnos.org
10 #include "RequestBuilder.h"
15 #include <util/Random.h>
18 #include "OpenState.h"
19 #include "RPCCallback.h"
20 #include "RPCCallbackServer.h"
23 RequestBuilder::RequestBuilder(Procedure proc
)
33 RequestBuilder::~RequestBuilder()
40 RequestBuilder::_InitHeader()
42 fRequest
= RPC::Call::Create(fProcedure
, RPC::Auth::CreateSys(),
43 RPC::Auth::CreateNone());
48 if (fProcedure
== ProcCompound
) {
49 fRequest
->Stream().AddOpaque(NULL
, 0);
50 fRequest
->Stream().AddUInt(0);
52 fOpCountPosition
= fRequest
->Stream().Current();
53 fRequest
->Stream().AddUInt(0);
59 RequestBuilder::Access()
61 if (fProcedure
!= ProcCompound
)
66 fRequest
->Stream().AddUInt(OpAccess
);
67 fRequest
->Stream().AddUInt(ACCESS4_READ
| ACCESS4_LOOKUP
| ACCESS4_MODIFY
68 | ACCESS4_EXTEND
| ACCESS4_DELETE
| ACCESS4_EXECUTE
);
76 RequestBuilder::Close(uint32 seq
, const uint32
* id
, uint32 stateSeq
)
78 if (fProcedure
!= ProcCompound
)
83 fRequest
->Stream().AddUInt(OpClose
);
84 fRequest
->Stream().AddUInt(seq
);
85 fRequest
->Stream().AddUInt(stateSeq
);
86 fRequest
->Stream().AddUInt(id
[0]);
87 fRequest
->Stream().AddUInt(id
[1]);
88 fRequest
->Stream().AddUInt(id
[2]);
97 RequestBuilder::Commit(uint64 offset
, uint32 count
)
99 if (fProcedure
!= ProcCompound
)
101 if (fRequest
== NULL
)
104 fRequest
->Stream().AddUInt(OpCommit
);
105 fRequest
->Stream().AddUHyper(offset
);
106 fRequest
->Stream().AddUInt(count
);
115 RequestBuilder::Create(FileType type
, const char* name
, AttrValue
* attr
,
116 uint32 count
, const char* path
)
118 if (fProcedure
!= ProcCompound
)
120 if (fRequest
== NULL
)
122 if (type
== NF4LNK
&& path
== NULL
)
126 if (type
== NF4BLK
|| type
== NF4CHR
)
129 fRequest
->Stream().AddUInt(OpCreate
);
130 fRequest
->Stream().AddUInt(type
);
132 fRequest
->Stream().AddString(path
);
133 fRequest
->Stream().AddString(name
);
134 _EncodeAttrs(fRequest
->Stream(), attr
, count
);
143 RequestBuilder::DelegReturn(const uint32
* id
, uint32 seq
)
145 if (fProcedure
!= ProcCompound
)
147 if (fRequest
== NULL
)
150 fRequest
->Stream().AddUInt(OpDelegReturn
);
152 fRequest
->Stream().AddUInt(seq
);
153 fRequest
->Stream().AddUInt(id
[0]);
154 fRequest
->Stream().AddUInt(id
[1]);
155 fRequest
->Stream().AddUInt(id
[2]);
164 RequestBuilder::GetAttr(Attribute
* attrs
, uint32 count
)
166 if (fProcedure
!= ProcCompound
)
168 if (fRequest
== NULL
)
171 fRequest
->Stream().AddUInt(OpGetAttr
);
172 _AttrBitmap(fRequest
->Stream(), attrs
, count
);
181 RequestBuilder::GetFH()
183 if (fProcedure
!= ProcCompound
)
185 if (fRequest
== NULL
)
188 fRequest
->Stream().AddUInt(OpGetFH
);
196 RequestBuilder::_GenerateLockOwner(XDR::WriteStream
& stream
,
197 OpenState
* state
, LockOwner
* owner
)
199 stream
.AddUHyper(state
->fClientID
);
202 lockOwner
[0] = owner
->fOwner
;
203 lockOwner
[1] = state
->fInfo
.fFileId
;
204 stream
.AddOpaque(lockOwner
, sizeof(lockOwner
));
209 RequestBuilder::Lock(OpenState
* state
, LockInfo
* lock
, uint32
* sequence
,
212 if (fProcedure
!= ProcCompound
)
214 if (fRequest
== NULL
)
217 fRequest
->Stream().AddUInt(OpLock
);
219 fRequest
->Stream().AddInt(lock
->fType
);
220 fRequest
->Stream().AddBoolean(reclaim
);
222 fRequest
->Stream().AddUHyper(lock
->fStart
);
223 fRequest
->Stream().AddUHyper(lock
->fLength
);
225 if (lock
->fOwner
->fStateId
[0] == 0 && lock
->fOwner
->fStateId
[1] == 0
226 && lock
->fOwner
->fStateId
[2] == 0) {
228 fRequest
->Stream().AddBoolean(true); // new lock owner
231 fRequest
->Stream().AddUInt(*sequence
);
232 fRequest
->Stream().AddUInt(state
->fStateSeq
);
233 fRequest
->Stream().AddUInt(state
->fStateID
[0]);
234 fRequest
->Stream().AddUInt(state
->fStateID
[1]);
235 fRequest
->Stream().AddUInt(state
->fStateID
[2]);
238 fRequest
->Stream().AddUInt(lock
->fOwner
->fSequence
++);
239 _GenerateLockOwner(fRequest
->Stream(), state
, lock
->fOwner
);
242 fRequest
->Stream().AddBoolean(false); // old lock owner
246 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateSeq
);
247 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[0]);
248 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[1]);
249 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[2]);
251 fRequest
->Stream().AddUInt(lock
->fOwner
->fSequence
++);
261 RequestBuilder::LockT(LockType type
, uint64 pos
, uint64 len
,
264 if (fProcedure
!= ProcCompound
)
266 if (fRequest
== NULL
)
269 fRequest
->Stream().AddUInt(OpLockT
);
271 fRequest
->Stream().AddInt(type
);
273 fRequest
->Stream().AddUHyper(pos
);
274 fRequest
->Stream().AddUHyper(len
);
276 fRequest
->Stream().AddUHyper(state
->fClientID
);
278 uint32 owner
= find_thread(NULL
);
279 fRequest
->Stream().AddOpaque(&owner
, sizeof(owner
));
288 RequestBuilder::LockU(LockInfo
* lock
)
290 if (fProcedure
!= ProcCompound
)
292 if (fRequest
== NULL
)
295 fRequest
->Stream().AddUInt(OpLockU
);
297 fRequest
->Stream().AddInt(lock
->fType
);
299 fRequest
->Stream().AddUInt(lock
->fOwner
->fSequence
++);
300 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateSeq
);
301 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[0]);
302 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[1]);
303 fRequest
->Stream().AddUInt(lock
->fOwner
->fStateId
[2]);
305 fRequest
->Stream().AddUHyper(lock
->fStart
);
306 fRequest
->Stream().AddUHyper(lock
->fLength
);
315 RequestBuilder::Link(const char* name
)
317 if (fProcedure
!= ProcCompound
)
319 if (fRequest
== NULL
)
324 fRequest
->Stream().AddUInt(OpLink
);
325 fRequest
->Stream().AddString(name
);
333 RequestBuilder::LookUp(const char* name
)
335 if (fProcedure
!= ProcCompound
)
337 if (fRequest
== NULL
)
342 fRequest
->Stream().AddUInt(OpLookUp
);
343 fRequest
->Stream().AddString(name
, strlen(name
));
351 RequestBuilder::LookUpUp()
353 if (fProcedure
!= ProcCompound
)
355 if (fRequest
== NULL
)
358 fRequest
->Stream().AddUInt(OpLookUpUp
);
366 RequestBuilder::Nverify(AttrValue
* attr
, uint32 count
)
368 if (fProcedure
!= ProcCompound
)
370 if (fRequest
== NULL
)
373 fRequest
->Stream().AddUInt(OpNverify
);
374 _EncodeAttrs(fRequest
->Stream(), attr
, count
);
383 RequestBuilder::Open(OpenClaim claim
, uint32 seq
, uint32 access
, uint64 id
,
384 OpenCreate oc
, uint64 ownerId
, const char* name
, AttrValue
* attr
,
385 uint32 count
, bool excl
, OpenDelegation delegationType
)
387 if (fProcedure
!= ProcCompound
)
389 if (fRequest
== NULL
)
392 fRequest
->Stream().AddUInt(OpOpen
);
393 fRequest
->Stream().AddUInt(seq
);
394 fRequest
->Stream().AddUInt(access
);
395 fRequest
->Stream().AddUInt(0); // deny none
396 fRequest
->Stream().AddUHyper(id
);
400 *(uint64
*)(owner
+ pos
) = ownerId
;
401 pos
+= sizeof(uint64
);
403 fRequest
->Stream().AddOpaque(owner
, pos
);
405 fRequest
->Stream().AddUInt(oc
);
406 if (oc
== OPEN4_CREATE
) {
407 fRequest
->Stream().AddInt(excl
? GUARDED4
: UNCHECKED4
);
408 _EncodeAttrs(fRequest
->Stream(), attr
, count
);
411 fRequest
->Stream().AddUInt(claim
);
414 fRequest
->Stream().AddString(name
, strlen(name
));
417 fRequest
->Stream().AddUInt(delegationType
);
420 return B_UNSUPPORTED
;
430 RequestBuilder::OpenConfirm(uint32 seq
, const uint32
* id
, uint32 stateSeq
)
432 if (fProcedure
!= ProcCompound
)
434 if (fRequest
== NULL
)
437 fRequest
->Stream().AddUInt(OpOpenConfirm
);
438 fRequest
->Stream().AddUInt(stateSeq
);
439 fRequest
->Stream().AddUInt(id
[0]);
440 fRequest
->Stream().AddUInt(id
[1]);
441 fRequest
->Stream().AddUInt(id
[2]);
442 fRequest
->Stream().AddUInt(seq
);
451 RequestBuilder::OpenAttrDir(bool create
)
453 if (fProcedure
!= ProcCompound
)
455 if (fRequest
== NULL
)
458 fRequest
->Stream().AddUInt(OpOpenAttrDir
);
459 fRequest
->Stream().AddBoolean(create
);
468 RequestBuilder::PutFH(const FileHandle
& fh
)
470 if (fProcedure
!= ProcCompound
)
472 if (fRequest
== NULL
)
475 fRequest
->Stream().AddUInt(OpPutFH
);
476 fRequest
->Stream().AddOpaque(fh
.fData
, fh
.fSize
);
484 RequestBuilder::PutRootFH()
486 if (fProcedure
!= ProcCompound
)
488 if (fRequest
== NULL
)
491 fRequest
->Stream().AddUInt(OpPutRootFH
);
499 RequestBuilder::Read(const uint32
* id
, uint32 stateSeq
, uint64 pos
, uint32 len
)
501 if (fProcedure
!= ProcCompound
)
503 if (fRequest
== NULL
)
506 fRequest
->Stream().AddUInt(OpRead
);
507 fRequest
->Stream().AddUInt(stateSeq
);
508 fRequest
->Stream().AddUInt(id
[0]);
509 fRequest
->Stream().AddUInt(id
[1]);
510 fRequest
->Stream().AddUInt(id
[2]);
511 fRequest
->Stream().AddUHyper(pos
);
512 fRequest
->Stream().AddUInt(len
);
521 RequestBuilder::ReadDir(uint64 cookie
, uint64 cookieVerf
, Attribute
* attrs
,
524 if (fProcedure
!= ProcCompound
)
526 if (fRequest
== NULL
)
529 fRequest
->Stream().AddUInt(OpReadDir
);
530 fRequest
->Stream().AddUHyper(cookie
);
531 fRequest
->Stream().AddUHyper(cookieVerf
);
533 // consider predicting this values basing on count or buffer size
534 fRequest
->Stream().AddUInt(0x2000);
535 fRequest
->Stream().AddUInt(0x8000);
536 _AttrBitmap(fRequest
->Stream(), attrs
, attrCount
);
545 RequestBuilder::ReadLink()
547 if (fProcedure
!= ProcCompound
)
549 if (fRequest
== NULL
)
552 fRequest
->Stream().AddUInt(OpReadLink
);
561 RequestBuilder::Remove(const char* file
)
563 if (fProcedure
!= ProcCompound
)
565 if (fRequest
== NULL
)
568 fRequest
->Stream().AddUInt(OpRemove
);
569 fRequest
->Stream().AddString(file
);
578 RequestBuilder::Rename(const char* from
, const char* to
)
580 if (fProcedure
!= ProcCompound
)
582 if (fRequest
== NULL
)
585 fRequest
->Stream().AddUInt(OpRename
);
586 fRequest
->Stream().AddString(from
);
587 fRequest
->Stream().AddString(to
);
596 RequestBuilder::Renew(uint64 clientId
)
598 if (fProcedure
!= ProcCompound
)
600 if (fRequest
== NULL
)
603 fRequest
->Stream().AddUInt(OpRenew
);
604 fRequest
->Stream().AddUHyper(clientId
);
613 RequestBuilder::SaveFH()
615 if (fProcedure
!= ProcCompound
)
617 if (fRequest
== NULL
)
620 fRequest
->Stream().AddUInt(OpSaveFH
);
628 RequestBuilder::SetAttr(const uint32
* id
, uint32 stateSeq
, AttrValue
* attr
,
631 if (fProcedure
!= ProcCompound
)
633 if (fRequest
== NULL
)
636 fRequest
->Stream().AddUInt(OpSetAttr
);
637 fRequest
->Stream().AddUInt(stateSeq
);
639 fRequest
->Stream().AddUInt(id
[0]);
640 fRequest
->Stream().AddUInt(id
[1]);
641 fRequest
->Stream().AddUInt(id
[2]);
643 fRequest
->Stream().AddUInt(0);
644 fRequest
->Stream().AddUInt(0);
645 fRequest
->Stream().AddUInt(0);
647 _EncodeAttrs(fRequest
->Stream(), attr
, count
);
656 RequestBuilder::SetClientID(RPC::Server
* server
)
658 if (fProcedure
!= ProcCompound
)
660 if (fRequest
== NULL
)
663 fRequest
->Stream().AddUInt(OpSetClientID
);
664 uint64 verifier
= get_random
<uint64
>();
665 fRequest
->Stream().AddUHyper(verifier
);
667 status_t result
= _GenerateClientId(fRequest
->Stream(), server
);
671 fRequest
->Stream().AddUInt(0x40000000);
673 if (server
->GetCallback() != NULL
) {
674 ASSERT(server
->GetCallback()->CBServer() != NULL
);
676 uint32 id
= server
->GetCallback()->ID();
678 PeerAddress local
= server
->GetCallback()->CBServer()->LocalID();
679 PeerAddress servAddr
= server
->LocalID();
680 servAddr
.SetPort(local
.Port());
682 fRequest
->Stream().AddString(local
.ProtocolString());
684 char* uAddr
= servAddr
.UniversalAddress();
687 fRequest
->Stream().AddString(uAddr
);
690 fRequest
->Stream().AddUInt(id
);
692 fRequest
->Stream().AddString("");
693 fRequest
->Stream().AddString("");
694 fRequest
->Stream().AddUInt(0);
704 RequestBuilder::_GenerateClientId(XDR::WriteStream
& stream
,
705 const RPC::Server
* server
)
707 char id
[512] = "HAIKU:kernel:";
708 int pos
= strlen(id
);
710 PeerAddress local
= server
->LocalID();
712 memcpy(id
+ pos
, server
->ID().InAddr(), server
->ID().InAddrSize());
713 pos
+= sizeof(server
->ID().InAddrSize());
715 memcpy(id
+ pos
, local
.InAddr(), local
.InAddrSize());
716 pos
+= sizeof(local
.InAddrSize());
718 *(uint16
*)(id
+ pos
) = server
->ID().Port();
719 pos
+= sizeof(uint16
);
721 *(uint16
*)(id
+ pos
) = server
->ID().fProtocol
;
722 pos
+= sizeof(uint16
);
724 stream
.AddOpaque(id
, pos
);
731 RequestBuilder::SetClientIDConfirm(uint64 id
, uint64 ver
)
733 if (fProcedure
!= ProcCompound
)
735 if (fRequest
== NULL
)
738 fRequest
->Stream().AddUInt(OpSetClientIDConfirm
);
739 fRequest
->Stream().AddUHyper(id
);
740 fRequest
->Stream().AddUHyper(ver
);
749 RequestBuilder::Verify(AttrValue
* attr
, uint32 count
)
751 if (fProcedure
!= ProcCompound
)
753 if (fRequest
== NULL
)
756 fRequest
->Stream().AddUInt(OpVerify
);
757 _EncodeAttrs(fRequest
->Stream(), attr
, count
);
766 RequestBuilder::Write(const uint32
* id
, uint32 stateSeq
, const void* buffer
,
767 uint64 pos
, uint32 len
, bool stable
)
769 if (fProcedure
!= ProcCompound
)
771 if (fRequest
== NULL
)
774 fRequest
->Stream().AddUInt(OpWrite
);
775 fRequest
->Stream().AddUInt(stateSeq
);
776 fRequest
->Stream().AddUInt(id
[0]);
777 fRequest
->Stream().AddUInt(id
[1]);
778 fRequest
->Stream().AddUInt(id
[2]);
779 fRequest
->Stream().AddUHyper(pos
);
780 fRequest
->Stream().AddInt(stable
? FILE_SYNC4
: UNSTABLE4
);
781 fRequest
->Stream().AddOpaque(buffer
, len
);
790 RequestBuilder::ReleaseLockOwner(OpenState
* state
, LockOwner
* owner
)
792 if (fProcedure
!= ProcCompound
)
794 if (fRequest
== NULL
)
797 fRequest
->Stream().AddUInt(OpReleaseLockOwner
);
798 _GenerateLockOwner(fRequest
->Stream(), state
, owner
);
807 RequestBuilder::Request()
809 if (fProcedure
== ProcCompound
)
810 fRequest
->Stream().InsertUInt(fOpCountPosition
, fOpCount
);
812 if (fRequest
== NULL
|| fRequest
->Stream().Error() == B_OK
)
820 RequestBuilder::_AttrBitmap(XDR::WriteStream
& stream
, Attribute
* attrs
,
823 // 2 is safe in NFS4, not in NFS4.1 though
825 memset(bitmap
, 0, sizeof(bitmap
));
826 for (uint32 i
= 0; i
< count
; i
++) {
827 bitmap
[attrs
[i
] / 32] |= 1 << attrs
[i
] % 32;
830 uint32 bcount
= bitmap
[1] != 0 ? 2 : 1;
831 stream
.AddUInt(bcount
);
832 for (uint32 i
= 0; i
< bcount
; i
++)
833 stream
.AddUInt(bitmap
[i
]);
838 RequestBuilder::_EncodeAttrs(XDR::WriteStream
& stream
, AttrValue
* attr
,
843 stream
.AddOpaque(NULL
, 0);
848 = reinterpret_cast<Attribute
*>(malloc(sizeof(Attribute
) * count
));
849 for (uint32 i
= 0; i
< count
; i
++)
850 attrs
[i
] = static_cast<Attribute
>(attr
[i
].fAttribute
);
851 _AttrBitmap(stream
, attrs
, count
);
855 XDR::WriteStream str
;
856 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_TYPE
) {
857 str
.AddUInt(attr
[i
].fData
.fValue32
);
861 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_SIZE
) {
862 str
.AddUHyper(attr
[i
].fData
.fValue64
);
866 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_FILEHANDLE
) {
867 FileHandle
* fh
= reinterpret_cast<FileHandle
*>(attr
[i
].fData
.fPointer
);
868 str
.AddOpaque(fh
->fData
, fh
->fSize
);
872 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_FILEID
) {
873 str
.AddUHyper(attr
[i
].fData
.fValue64
);
877 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_MODE
) {
878 str
.AddUInt(attr
[i
].fData
.fValue32
);
882 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_OWNER
) {
883 str
.AddString(reinterpret_cast<char*>(attr
[i
].fData
.fPointer
));
887 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_OWNER_GROUP
) {
888 str
.AddString(reinterpret_cast<char*>(attr
[i
].fData
.fPointer
));
892 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_TIME_ACCESS_SET
) {
893 str
.AddInt(1); // SET_TO_CLIENT_TIME4
896 = reinterpret_cast<timespec
*>(attr
[i
].fData
.fPointer
);
897 str
.AddHyper(ts
->tv_sec
);
898 str
.AddUInt(ts
->tv_nsec
);
903 if (i
< count
&& attr
[i
].fAttribute
== FATTR4_TIME_MODIFY_SET
) {
904 str
.AddInt(1); // SET_TO_CLIENT_TIME4
907 = reinterpret_cast<timespec
*>(attr
[i
].fData
.fPointer
);
908 str
.AddHyper(ts
->tv_sec
);
909 str
.AddUInt(ts
->tv_nsec
);
914 stream
.AddOpaque(str
);